From 8ed330871411fd5fe08c5bdefea9017d21b6250a Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Wed, 8 Jun 2011 11:07:32 +0530 Subject: Stagging : AB5500 SIM interface Driver SIM Interface driver provides interface to configure various parameters of AB5500 SIM Level Shifter. Support provided are: Configure Pull up on sim lines Configure Operation Mode Notify Sim Insert/Extract Interrupt ST-Ericsson Linux next: 336280 ST-Ericsson ID: 341172 ST-Ericsson FOSS-OUT ID:STETL-FOSS-OUT-10242 Change-Id: I5ef4b92384ca4da0f96839afae7c7468f244978f Signed-off-by: Bibek Basu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21582 Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/staging/ab5500_sim/Makefile | 1 + drivers/staging/ab5500_sim/ab5500-sim.c | 299 ++++++++++++++++++++++++++++++++ drivers/staging/ab5500_sim/sysfs-sim | 83 +++++++++ 3 files changed, 383 insertions(+) create mode 100644 drivers/staging/ab5500_sim/Makefile create mode 100644 drivers/staging/ab5500_sim/ab5500-sim.c create mode 100644 drivers/staging/ab5500_sim/sysfs-sim (limited to 'drivers/staging') diff --git a/drivers/staging/ab5500_sim/Makefile b/drivers/staging/ab5500_sim/Makefile new file mode 100644 index 00000000000..520717e4dd7 --- /dev/null +++ b/drivers/staging/ab5500_sim/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_AB5500_SIM) += ab5500-sim.o diff --git a/drivers/staging/ab5500_sim/ab5500-sim.c b/drivers/staging/ab5500_sim/ab5500-sim.c new file mode 100644 index 00000000000..788a7984a46 --- /dev/null +++ b/drivers/staging/ab5500_sim/ab5500-sim.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) ST Ericsson SA 2010 + * + * Sim Interface driver for AB5500 + * + * License Terms: GNU General Public License v2 + * Author: Bibek Basu + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USIM_SUP2_REG 0x13 +#define USIM_SUP_REG 0x14 +#define USIM_SIMCTRL_REG 0x17 +#define USIM_SIMCTRL2_REG 0x18 +#define USIM_USBUICC_REG 0x19 +#define USIM_USBUICC2_REG 0x20 +#define SIM_DAT_PULLUP_10K 0x0F +#define SIM_LDO_1_8V 1875000 +#define SIM_LDO_2_8V 2800000 +#define SIM_LDO_2_9V 2900000 + +enum shift { + SHIFT0, + SHIFT1, + SHIFT2, + SHIFT3, + SHIFT4, + SHIFT5, + SHIFT6, + SHIFT7, +}; + +enum mask { + MASK1 = 1, + MASK3 = 3, + MASK7 = 7, +}; + +enum sim_mode { + OFF_MODE, + LOW_PWR, + PWRCTRL, + FULL_PWR, +}; +/** + * struct ab5500_sim - ab5500 Sim Interface device information + * @dev: pointer to the structure device + * @lock: mutex lock + * @sim_int_status: Sim presence status + * @irq_base: Base of the two irqs + */ +struct ab5500_sim { + struct device *dev; + struct mutex lock; + bool sim_int_status; + u8 irq_base; +}; + +/* Exposure to the sysfs interface */ +int ab5500_sim_weak_pulldforce(struct device *dev, + struct device_attribute *attr, + const char *user_buf, size_t count) +{ + unsigned long user_val; + int err; + bool enable; + + err = strict_strtoul(user_buf, 0, &user_val); + if (err) + return -EINVAL; + enable = user_val ? true : false; + err = abx500_mask_and_set(dev, AB5500_BANK_SIM_USBSIM, + USIM_USBUICC2_REG, MASK1 << SHIFT5, user_val << SHIFT5); + if (err) + return -EINVAL; + return count; +} + +int ab5500_sim_load_sel(struct device *dev, + struct device_attribute *attr, + const char *user_buf, size_t count) +{ + unsigned long user_val; + int err; + bool enable; + + err = strict_strtoul(user_buf, 0, &user_val); + if (err) + return -EINVAL; + enable = user_val ? true : false; + err = abx500_mask_and_set(dev, AB5500_BANK_SIM_USBSIM, + USIM_USBUICC_REG, MASK1 << SHIFT1, user_val << SHIFT1); + if (err) + return -EINVAL; + return count; +} + +int ab5500_sim_mode_sel(struct device *dev, + struct device_attribute *attr, + const char *user_buf, size_t count) +{ + unsigned long user_val; + int err; + + err = strict_strtoul(user_buf, 0, &user_val); + if (err) + return -EINVAL; + err = abx500_mask_and_set(dev, AB5500_BANK_SIM_USBSIM, + USIM_SIMCTRL2_REG, MASK3 << SHIFT4, user_val << SHIFT4); + if (err) + return -EINVAL; + return count; +} + +int ab5500_sim_dat_pullup(struct device *dev, + struct device_attribute *attr, + const char *user_buf, size_t count) +{ + unsigned long user_val; + int err; + + err = strict_strtoul(user_buf, 0, &user_val); + if (err) + return -EINVAL; + err = abx500_mask_and_set(dev, AB5500_BANK_SIM_USBSIM, + USIM_SIMCTRL_REG, MASK7, user_val); + if (err) + return -EINVAL; + return count; +} + +int ab5500_sim_enable_pullup(struct device *dev, + struct device_attribute *attr, + const char *user_buf, size_t count) +{ + unsigned long user_val; + int err; + bool enable; + + err = strict_strtoul(user_buf, 0, &user_val); + if (err) + return -EINVAL; + enable = user_val ? true : false; + err = abx500_mask_and_set(dev, AB5500_BANK_SIM_USBSIM, + USIM_SIMCTRL_REG, MASK1 << SHIFT3, enable << SHIFT3); + if (err) + return -EINVAL; + return count; +} + +static ssize_t ab5500_simoff_int(struct device *dev, + struct device_attribute *devattr, char *user_buf) +{ + struct ab5500_sim *di = dev_get_drvdata(dev); + int len; + + mutex_lock(&di->lock); + len = sprintf(user_buf, "%d\n", di->sim_int_status); + mutex_unlock(&di->lock); + return len; +} + +static DEVICE_ATTR(enable_pullup, S_IWUSR, NULL, ab5500_sim_enable_pullup); +static DEVICE_ATTR(dat_pullup, S_IWUSR, NULL, ab5500_sim_dat_pullup); +static DEVICE_ATTR(mode_sel, S_IWUSR, NULL, ab5500_sim_mode_sel); +static DEVICE_ATTR(load_sel, S_IWUSR, NULL, ab5500_sim_load_sel); +static DEVICE_ATTR(weak_pulldforce, S_IWUSR, NULL, ab5500_sim_weak_pulldforce); +static DEVICE_ATTR(simoff_int, S_IRUGO, ab5500_simoff_int, NULL); + +static struct attribute *ab5500_sim_attributes[] = { + &dev_attr_enable_pullup.attr, + &dev_attr_dat_pullup.attr, + &dev_attr_mode_sel.attr, + &dev_attr_load_sel.attr, + &dev_attr_weak_pulldforce.attr, + &dev_attr_simoff_int.attr, + NULL +}; + +static const struct attribute_group ab5500sim_attr_grp = { + .attrs = ab5500_sim_attributes, +}; + +static irqreturn_t ab5500_sim_irq_handler(int irq, void *irq_data) +{ + struct platform_device *pdev = irq_data; + struct ab5500_sim *data = platform_get_drvdata(pdev); + + if (irq == data->irq_base) + data->sim_int_status = true; + else + data->sim_int_status = false; + sysfs_notify(&pdev->dev.kobj, NULL, "simoff_int"); + + return IRQ_HANDLED; +} + +static int __devexit ab5500_sim_remove(struct platform_device *pdev) +{ + struct ab5500_sim *di = platform_get_drvdata(pdev); + int irq = platform_get_irq_byname(pdev, "SIMOFF"); + + if (irq >= 0) { + free_irq(irq, di); + irq++; + free_irq(irq, di); + } + sysfs_remove_group(&pdev->dev.kobj, &ab5500sim_attr_grp); + platform_set_drvdata(pdev, NULL); + kfree(di); + + return 0; +} + +static int __devinit ab5500_sim_probe(struct platform_device *pdev) +{ + int ret = 0; + int irq; + struct ab5500_sim *di = + kzalloc(sizeof(struct ab5500_sim), GFP_KERNEL); + if (!di) + return -ENOMEM; + + dev_info(&pdev->dev, "ab5500_sim_driver PROBE\n"); + irq = platform_get_irq_byname(pdev, "SIMOFF"); + if (irq < 0) { + dev_err(&pdev->dev, "Get irq by name failed\n"); + return irq; + } + di->irq_base = irq; + di->dev = &pdev->dev; + mutex_init(&di->lock); + platform_set_drvdata(pdev, di); + /* sysfs interface to configure sim reg from user space */ + if (sysfs_create_group(&pdev->dev.kobj, &ab5500sim_attr_grp) < 0) { + dev_err(&pdev->dev, " Failed creating sysfs group\n"); + return -ENOMEM; + } + ret = request_threaded_irq(irq, NULL, ab5500_sim_irq_handler, + IRQF_NO_SUSPEND , "ab5500-sim", pdev); + if (ret < 0) { + dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); + goto exit; + } + /* this is the contiguous irq for sim removal,falling edge */ + irq = irq + 1; + ret = request_threaded_irq(irq, NULL, ab5500_sim_irq_handler, + IRQF_NO_SUSPEND , "ab5500-sim", pdev); + if (ret < 0) { + dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); + free_irq(--irq, di); + goto exit; + } + return ret; +exit: + sysfs_remove_group(&pdev->dev.kobj, &ab5500sim_attr_grp); + platform_set_drvdata(pdev, NULL); + kfree(di); + return ret; +} + +static struct platform_driver ab5500_sim_driver = { + .probe = ab5500_sim_probe, + .remove = __devexit_p(ab5500_sim_remove), + .driver = { + .name = "ab5500-sim", + .owner = THIS_MODULE, + }, +}; + +static int __init ab5500_sim_init(void) +{ + return platform_driver_register(&ab5500_sim_driver); +} + +static void __exit ab5500_sim_exit(void) +{ + platform_driver_unregister(&ab5500_sim_driver); +} + +module_init(ab5500_sim_init); +module_exit(ab5500_sim_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Bibek Basu"); +MODULE_ALIAS("platform:ab5500-sim"); +MODULE_DESCRIPTION("AB5500 sim interface driver"); diff --git a/drivers/staging/ab5500_sim/sysfs-sim b/drivers/staging/ab5500_sim/sysfs-sim new file mode 100644 index 00000000000..b809b21e39e --- /dev/null +++ b/drivers/staging/ab5500_sim/sysfs-sim @@ -0,0 +1,83 @@ +What: /sys/devices/platform/ab5500-core.0/ab5500-sim.4/ +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4 directory contains attributes + allowing the user space to check and configure ab5500 sim level + shifter interface caracteristics for communication to SIM card + +What: /sys/devices/.../enable_pullup +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4/enable_pullup attribute allows + the user space to configure if internal pull up in SIMIO lines + has to be enabled or disabled. For enabling write 1 to the file + and 0 for disabling + + +What: /sys/devices/.../dat_pullup +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4/dat_pullup attribute allows + the user space to configure the resistance value for internal + pull up in SIMIO lines. Following value can be written on the file + 0 SIM_DAT pull-up disabled + 1 SIM_DAT pull-up 4kOhm + 2 SIM_DAT pull-up 5kOhm + 3 SIM_DAT pull-up 6kOhm + 4 SIM_DAT pull-up 7kOhm + 5 SIM_DAT pull-up 8kOhm + 6 SIM_DAT pull-up 9kOhm + 7 SIM_DAT pull-up 10kOhm + +What: /sys/devices/.../mode_sel +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4/mode_sel attribute allows + the user space to configure the mode at which the level shifter + will work. Following value can be written on the file + 0 TG mode and LI mode off + 1 TG mode on + 2 LI mode on + 3 TG mode and LI mode off + +What: /sys/devices/.../load_sel +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4/load_sel attribute allows + the user space to configure the load on the USBUICC lines. + Following value can be written on the file. + 0 Data line load < 21pF + 1 Data line load 21-30pF + +What: /sys/devices/.../weak_pulldforce +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4/weak_pulldforce attribute allows + the user space to configure the weak pull down on the USBUICC lines. + Following value can be written on the file. + 0 USB-UICC data lines weak pull down active + 1 USB-UICC data lines weak pull down not active + +What: /sys/devices/.../simoff_int +Date: June 2011 +KernelVersion: 2.6.35 +Contact: Bibek Basu +Description: + The /sys/devices/.../ab5500-sim.4/simoff_int attribute allows + the user space to poll this file and get notified in case a sim + hot swap has happened. a zero means sim extracetd and a one means + inserted. + + -- cgit v1.2.3 From afb68c88f151dfa304db91e6f9951dade0a464e6 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Wed, 17 Aug 2011 13:45:01 +0530 Subject: ux500_ing05160_ab5500_sim_0.1: fix the resource leak Commit id : I70c297af: staging ab5500-sim: fix the resource leak Build and boot test only done for 8500 config Booting will only happend properly if used Initramfs Signed-off-by: Bibek Basu Change-Id: I8edbdb1dbf4282b8bfa4e6b5a3f4b0ca2b460138 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28916 --- drivers/staging/ab5500_sim/ab5500-sim.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/staging') diff --git a/drivers/staging/ab5500_sim/ab5500-sim.c b/drivers/staging/ab5500_sim/ab5500-sim.c index 788a7984a46..3f4ae7cd34a 100644 --- a/drivers/staging/ab5500_sim/ab5500-sim.c +++ b/drivers/staging/ab5500_sim/ab5500-sim.c @@ -230,14 +230,16 @@ static int __devinit ab5500_sim_probe(struct platform_device *pdev) int irq; struct ab5500_sim *di = kzalloc(sizeof(struct ab5500_sim), GFP_KERNEL); - if (!di) - return -ENOMEM; - + if (!di) { + ret = -ENOMEM; + goto error_alloc; + } dev_info(&pdev->dev, "ab5500_sim_driver PROBE\n"); irq = platform_get_irq_byname(pdev, "SIMOFF"); if (irq < 0) { dev_err(&pdev->dev, "Get irq by name failed\n"); - return irq; + ret = irq; + goto exit; } di->irq_base = irq; di->dev = &pdev->dev; @@ -246,13 +248,14 @@ static int __devinit ab5500_sim_probe(struct platform_device *pdev) /* sysfs interface to configure sim reg from user space */ if (sysfs_create_group(&pdev->dev.kobj, &ab5500sim_attr_grp) < 0) { dev_err(&pdev->dev, " Failed creating sysfs group\n"); - return -ENOMEM; + ret = -ENOMEM; + goto error_sysfs; } ret = request_threaded_irq(irq, NULL, ab5500_sim_irq_handler, IRQF_NO_SUSPEND , "ab5500-sim", pdev); if (ret < 0) { dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); - goto exit; + goto error_irq; } /* this is the contiguous irq for sim removal,falling edge */ irq = irq + 1; @@ -261,13 +264,16 @@ static int __devinit ab5500_sim_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "Request threaded irq failed (%d)\n", ret); free_irq(--irq, di); - goto exit; + goto error_irq; } return ret; -exit: +error_irq: sysfs_remove_group(&pdev->dev.kobj, &ab5500sim_attr_grp); +error_sysfs: platform_set_drvdata(pdev, NULL); +exit: kfree(di); +error_alloc: return ret; } -- cgit v1.2.3 From 5343fdf6aa71df71978803b0a826a1f2e0b3b921 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 08:48:46 +0200 Subject: ab5500: move to separate header --- drivers/staging/ab5500_sim/ab5500-sim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/staging') diff --git a/drivers/staging/ab5500_sim/ab5500-sim.c b/drivers/staging/ab5500_sim/ab5500-sim.c index 3f4ae7cd34a..d222a22ed24 100644 --- a/drivers/staging/ab5500_sim/ab5500-sim.c +++ b/drivers/staging/ab5500_sim/ab5500-sim.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From df2d23c69df125ec12ca3cf2babc5acfd4159a85 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 17 Nov 2011 15:45:34 +0100 Subject: staging: Add AB5500 SIM interface Driver Compilation Signed-off-by: Philippe Langlais --- drivers/staging/Kconfig | 10 ++++++++++ drivers/staging/Makefile | 1 + 2 files changed, 11 insertions(+) (limited to 'drivers/staging') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 97d412d9145..eeac488e3be 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -24,6 +24,16 @@ menuconfig STAGING if STAGING +config AB5500_SIM + bool "ST-Ericsson AB5500 SIM Interface driver" + depends on AB5500_CORE + help + SIM Interface driver provides interface to configure + various parameters of AB5550 SIM Level Shifter.Support provided are: + Configure Pull up on sim lines + Configure Operation Mode + Notify Sim Insert/Extract Interrupt + source "drivers/staging/serial/Kconfig" source "drivers/staging/et131x/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ffe7d44374e..c6f1f5e35fd 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ +obj-$(CONFIG_AB5500_SIM) += ab5500_sim/ -- cgit v1.2.3