diff options
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/Kconfig | 12 | ||||
-rw-r--r-- | drivers/mfd/asic3.c | 8 | ||||
-rw-r--r-- | drivers/mfd/htc-egpio.c | 2 | ||||
-rw-r--r-- | drivers/mfd/htc-pasic3.c | 2 | ||||
-rw-r--r-- | drivers/mfd/mcp-sa11x0.c | 2 | ||||
-rw-r--r-- | drivers/mfd/mfd-core.c | 2 | ||||
-rw-r--r-- | drivers/mfd/sm501.c | 439 |
7 files changed, 408 insertions, 59 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9f93c29fed35..883e7ea31de2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -19,6 +19,14 @@ config MFD_SM501 | |||
19 | interface. The device may be connected by PCI or local bus with | 19 | interface. The device may be connected by PCI or local bus with |
20 | varying functions enabled. | 20 | varying functions enabled. |
21 | 21 | ||
22 | config MFD_SM501_GPIO | ||
23 | bool "Export GPIO via GPIO layer" | ||
24 | depends on MFD_SM501 && HAVE_GPIO_LIB | ||
25 | ---help--- | ||
26 | This option uses the gpio library layer to export the 64 GPIO | ||
27 | lines on the SM501. The platform data is used to supply the | ||
28 | base number for the first GPIO line to register. | ||
29 | |||
22 | config MFD_ASIC3 | 30 | config MFD_ASIC3 |
23 | bool "Support for Compaq ASIC3" | 31 | bool "Support for Compaq ASIC3" |
24 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM | 32 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM |
@@ -28,7 +36,7 @@ config MFD_ASIC3 | |||
28 | 36 | ||
29 | config HTC_EGPIO | 37 | config HTC_EGPIO |
30 | bool "HTC EGPIO support" | 38 | bool "HTC EGPIO support" |
31 | depends on GENERIC_HARDIRQS && HAVE_GPIO_LIB && ARM | 39 | depends on GENERIC_HARDIRQS && GPIOLIB && ARM |
32 | help | 40 | help |
33 | This driver supports the CPLD egpio chip present on | 41 | This driver supports the CPLD egpio chip present on |
34 | several HTC phones. It provides basic support for input | 42 | several HTC phones. It provides basic support for input |
@@ -44,7 +52,7 @@ config HTC_PASIC3 | |||
44 | 52 | ||
45 | config MFD_TC6393XB | 53 | config MFD_TC6393XB |
46 | bool "Support Toshiba TC6393XB" | 54 | bool "Support Toshiba TC6393XB" |
47 | depends on HAVE_GPIO_LIB | 55 | depends on GPIOLIB && ARM |
48 | select MFD_CORE | 56 | select MFD_CORE |
49 | help | 57 | help |
50 | Support for Toshiba Mobile IO Controller TC6393XB | 58 | Support for Toshiba Mobile IO Controller TC6393XB |
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 3b870e7fb3e1..eabf0bfccab4 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
@@ -314,10 +314,12 @@ static int __init asic3_irq_probe(struct platform_device *pdev) | |||
314 | unsigned long clksel = 0; | 314 | unsigned long clksel = 0; |
315 | unsigned int irq, irq_base; | 315 | unsigned int irq, irq_base; |
316 | int map_size; | 316 | int map_size; |
317 | int ret; | ||
317 | 318 | ||
318 | asic->irq_nr = platform_get_irq(pdev, 0); | 319 | ret = platform_get_irq(pdev, 0); |
319 | if (asic->irq_nr < 0) | 320 | if (ret < 0) |
320 | return asic->irq_nr; | 321 | return ret; |
322 | asic->irq_nr = ret; | ||
321 | 323 | ||
322 | /* turn on clock to IRQ controller */ | 324 | /* turn on clock to IRQ controller */ |
323 | clksel |= CLOCK_SEL_CX; | 325 | clksel |= CLOCK_SEL_CX; |
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c index 8872cc077519..6be43172dc65 100644 --- a/drivers/mfd/htc-egpio.c +++ b/drivers/mfd/htc-egpio.c | |||
@@ -318,6 +318,8 @@ static int __init egpio_probe(struct platform_device *pdev) | |||
318 | ei->chip[i].dev = &(pdev->dev); | 318 | ei->chip[i].dev = &(pdev->dev); |
319 | chip = &(ei->chip[i].chip); | 319 | chip = &(ei->chip[i].chip); |
320 | chip->label = "htc-egpio"; | 320 | chip->label = "htc-egpio"; |
321 | chip->dev = &pdev->dev; | ||
322 | chip->owner = THIS_MODULE; | ||
321 | chip->get = egpio_get; | 323 | chip->get = egpio_get; |
322 | chip->set = egpio_set; | 324 | chip->set = egpio_set; |
323 | chip->direction_input = egpio_direction_input; | 325 | chip->direction_input = egpio_direction_input; |
diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index 633cbba072f0..91b294dcc133 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c | |||
@@ -238,6 +238,8 @@ static int pasic3_remove(struct platform_device *pdev) | |||
238 | return 0; | 238 | return 0; |
239 | } | 239 | } |
240 | 240 | ||
241 | MODULE_ALIAS("platform:pasic3"); | ||
242 | |||
241 | static struct platform_driver pasic3_driver = { | 243 | static struct platform_driver pasic3_driver = { |
242 | .driver = { | 244 | .driver = { |
243 | .name = "pasic3", | 245 | .name = "pasic3", |
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c index 1eab7cffceaa..b5272b5ce3fa 100644 --- a/drivers/mfd/mcp-sa11x0.c +++ b/drivers/mfd/mcp-sa11x0.c | |||
@@ -242,6 +242,8 @@ static int mcp_sa11x0_resume(struct platform_device *dev) | |||
242 | /* | 242 | /* |
243 | * The driver for the SA11x0 MCP port. | 243 | * The driver for the SA11x0 MCP port. |
244 | */ | 244 | */ |
245 | MODULE_ALIAS("platform:sa11x0-mcp"); | ||
246 | |||
245 | static struct platform_driver mcp_sa11x0_driver = { | 247 | static struct platform_driver mcp_sa11x0_driver = { |
246 | .probe = mcp_sa11x0_probe, | 248 | .probe = mcp_sa11x0_probe, |
247 | .remove = mcp_sa11x0_remove, | 249 | .remove = mcp_sa11x0_remove, |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index d7d88ce053a6..0454be4266c1 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -36,7 +36,7 @@ static int mfd_add_device(struct platform_device *parent, | |||
36 | if (ret) | 36 | if (ret) |
37 | goto fail_device; | 37 | goto fail_device; |
38 | 38 | ||
39 | memzero(res, sizeof(res)); | 39 | memset(res, 0, sizeof(res)); |
40 | for (r = 0; r < cell->num_resources; r++) { | 40 | for (r = 0; r < cell->num_resources; r++) { |
41 | res[r].name = cell->resources[r].name; | 41 | res[r].name = cell->resources[r].name; |
42 | res[r].flags = cell->resources[r].flags; | 42 | res[r].flags = cell->resources[r].flags; |
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c index 2fe64734d8af..7aebad4c06ff 100644 --- a/drivers/mfd/sm501.c +++ b/drivers/mfd/sm501.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
22 | #include <linux/i2c-gpio.h> | ||
22 | 23 | ||
23 | #include <linux/sm501.h> | 24 | #include <linux/sm501.h> |
24 | #include <linux/sm501-regs.h> | 25 | #include <linux/sm501-regs.h> |
@@ -31,10 +32,37 @@ struct sm501_device { | |||
31 | struct platform_device pdev; | 32 | struct platform_device pdev; |
32 | }; | 33 | }; |
33 | 34 | ||
35 | struct sm501_gpio; | ||
36 | |||
37 | #ifdef CONFIG_MFD_SM501_GPIO | ||
38 | #include <linux/gpio.h> | ||
39 | |||
40 | struct sm501_gpio_chip { | ||
41 | struct gpio_chip gpio; | ||
42 | struct sm501_gpio *ourgpio; /* to get back to parent. */ | ||
43 | void __iomem *regbase; | ||
44 | }; | ||
45 | |||
46 | struct sm501_gpio { | ||
47 | struct sm501_gpio_chip low; | ||
48 | struct sm501_gpio_chip high; | ||
49 | spinlock_t lock; | ||
50 | |||
51 | unsigned int registered : 1; | ||
52 | void __iomem *regs; | ||
53 | struct resource *regs_res; | ||
54 | }; | ||
55 | #else | ||
56 | struct sm501_gpio { | ||
57 | /* no gpio support, empty definition for sm501_devdata. */ | ||
58 | }; | ||
59 | #endif | ||
60 | |||
34 | struct sm501_devdata { | 61 | struct sm501_devdata { |
35 | spinlock_t reg_lock; | 62 | spinlock_t reg_lock; |
36 | struct mutex clock_lock; | 63 | struct mutex clock_lock; |
37 | struct list_head devices; | 64 | struct list_head devices; |
65 | struct sm501_gpio gpio; | ||
38 | 66 | ||
39 | struct device *dev; | 67 | struct device *dev; |
40 | struct resource *io_res; | 68 | struct resource *io_res; |
@@ -42,6 +70,7 @@ struct sm501_devdata { | |||
42 | struct resource *regs_claim; | 70 | struct resource *regs_claim; |
43 | struct sm501_platdata *platdata; | 71 | struct sm501_platdata *platdata; |
44 | 72 | ||
73 | |||
45 | unsigned int in_suspend; | 74 | unsigned int in_suspend; |
46 | unsigned long pm_misc; | 75 | unsigned long pm_misc; |
47 | 76 | ||
@@ -52,6 +81,7 @@ struct sm501_devdata { | |||
52 | unsigned int rev; | 81 | unsigned int rev; |
53 | }; | 82 | }; |
54 | 83 | ||
84 | |||
55 | #define MHZ (1000 * 1000) | 85 | #define MHZ (1000 * 1000) |
56 | 86 | ||
57 | #ifdef DEBUG | 87 | #ifdef DEBUG |
@@ -276,58 +306,6 @@ unsigned long sm501_modify_reg(struct device *dev, | |||
276 | 306 | ||
277 | EXPORT_SYMBOL_GPL(sm501_modify_reg); | 307 | EXPORT_SYMBOL_GPL(sm501_modify_reg); |
278 | 308 | ||
279 | unsigned long sm501_gpio_get(struct device *dev, | ||
280 | unsigned long gpio) | ||
281 | { | ||
282 | struct sm501_devdata *sm = dev_get_drvdata(dev); | ||
283 | unsigned long result; | ||
284 | unsigned long reg; | ||
285 | |||
286 | reg = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW; | ||
287 | result = readl(sm->regs + reg); | ||
288 | |||
289 | result >>= (gpio & 31); | ||
290 | return result & 1UL; | ||
291 | } | ||
292 | |||
293 | EXPORT_SYMBOL_GPL(sm501_gpio_get); | ||
294 | |||
295 | void sm501_gpio_set(struct device *dev, | ||
296 | unsigned long gpio, | ||
297 | unsigned int to, | ||
298 | unsigned int dir) | ||
299 | { | ||
300 | struct sm501_devdata *sm = dev_get_drvdata(dev); | ||
301 | |||
302 | unsigned long bit = 1 << (gpio & 31); | ||
303 | unsigned long base; | ||
304 | unsigned long save; | ||
305 | unsigned long val; | ||
306 | |||
307 | base = (gpio > 32) ? SM501_GPIO_DATA_HIGH : SM501_GPIO_DATA_LOW; | ||
308 | base += SM501_GPIO; | ||
309 | |||
310 | spin_lock_irqsave(&sm->reg_lock, save); | ||
311 | |||
312 | val = readl(sm->regs + base) & ~bit; | ||
313 | if (to) | ||
314 | val |= bit; | ||
315 | writel(val, sm->regs + base); | ||
316 | |||
317 | val = readl(sm->regs + SM501_GPIO_DDR_LOW) & ~bit; | ||
318 | if (dir) | ||
319 | val |= bit; | ||
320 | |||
321 | writel(val, sm->regs + SM501_GPIO_DDR_LOW); | ||
322 | sm501_sync_regs(sm); | ||
323 | |||
324 | spin_unlock_irqrestore(&sm->reg_lock, save); | ||
325 | |||
326 | } | ||
327 | |||
328 | EXPORT_SYMBOL_GPL(sm501_gpio_set); | ||
329 | |||
330 | |||
331 | /* sm501_unit_power | 309 | /* sm501_unit_power |
332 | * | 310 | * |
333 | * alters the power active gate to set specific units on or off | 311 | * alters the power active gate to set specific units on or off |
@@ -906,6 +884,313 @@ static int sm501_register_display(struct sm501_devdata *sm, | |||
906 | return sm501_register_device(sm, pdev); | 884 | return sm501_register_device(sm, pdev); |
907 | } | 885 | } |
908 | 886 | ||
887 | #ifdef CONFIG_MFD_SM501_GPIO | ||
888 | |||
889 | static inline struct sm501_gpio_chip *to_sm501_gpio(struct gpio_chip *gc) | ||
890 | { | ||
891 | return container_of(gc, struct sm501_gpio_chip, gpio); | ||
892 | } | ||
893 | |||
894 | static inline struct sm501_devdata *sm501_gpio_to_dev(struct sm501_gpio *gpio) | ||
895 | { | ||
896 | return container_of(gpio, struct sm501_devdata, gpio); | ||
897 | } | ||
898 | |||
899 | static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
900 | |||
901 | { | ||
902 | struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip); | ||
903 | unsigned long result; | ||
904 | |||
905 | result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW); | ||
906 | result >>= offset; | ||
907 | |||
908 | return result & 1UL; | ||
909 | } | ||
910 | |||
911 | static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
912 | |||
913 | { | ||
914 | struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); | ||
915 | struct sm501_gpio *smgpio = smchip->ourgpio; | ||
916 | unsigned long bit = 1 << offset; | ||
917 | void __iomem *regs = smchip->regbase; | ||
918 | unsigned long save; | ||
919 | unsigned long val; | ||
920 | |||
921 | dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n", | ||
922 | __func__, chip, offset); | ||
923 | |||
924 | spin_lock_irqsave(&smgpio->lock, save); | ||
925 | |||
926 | val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit; | ||
927 | if (value) | ||
928 | val |= bit; | ||
929 | writel(val, regs); | ||
930 | |||
931 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
932 | spin_unlock_irqrestore(&smgpio->lock, save); | ||
933 | } | ||
934 | |||
935 | static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset) | ||
936 | { | ||
937 | struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); | ||
938 | struct sm501_gpio *smgpio = smchip->ourgpio; | ||
939 | void __iomem *regs = smchip->regbase; | ||
940 | unsigned long bit = 1 << offset; | ||
941 | unsigned long save; | ||
942 | unsigned long ddr; | ||
943 | |||
944 | dev_info(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d)\n", | ||
945 | __func__, chip, offset); | ||
946 | |||
947 | spin_lock_irqsave(&smgpio->lock, save); | ||
948 | |||
949 | ddr = readl(regs + SM501_GPIO_DDR_LOW); | ||
950 | writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW); | ||
951 | |||
952 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
953 | spin_unlock_irqrestore(&smgpio->lock, save); | ||
954 | |||
955 | return 0; | ||
956 | } | ||
957 | |||
958 | static int sm501_gpio_output(struct gpio_chip *chip, | ||
959 | unsigned offset, int value) | ||
960 | { | ||
961 | struct sm501_gpio_chip *smchip = to_sm501_gpio(chip); | ||
962 | struct sm501_gpio *smgpio = smchip->ourgpio; | ||
963 | unsigned long bit = 1 << offset; | ||
964 | void __iomem *regs = smchip->regbase; | ||
965 | unsigned long save; | ||
966 | unsigned long val; | ||
967 | unsigned long ddr; | ||
968 | |||
969 | dev_dbg(sm501_gpio_to_dev(smgpio)->dev, "%s(%p,%d,%d)\n", | ||
970 | __func__, chip, offset, value); | ||
971 | |||
972 | spin_lock_irqsave(&smgpio->lock, save); | ||
973 | |||
974 | val = readl(regs + SM501_GPIO_DATA_LOW); | ||
975 | if (value) | ||
976 | val |= bit; | ||
977 | else | ||
978 | val &= ~bit; | ||
979 | writel(val, regs); | ||
980 | |||
981 | ddr = readl(regs + SM501_GPIO_DDR_LOW); | ||
982 | writel(ddr | bit, regs + SM501_GPIO_DDR_LOW); | ||
983 | |||
984 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
985 | writel(val, regs + SM501_GPIO_DATA_LOW); | ||
986 | |||
987 | sm501_sync_regs(sm501_gpio_to_dev(smgpio)); | ||
988 | spin_unlock_irqrestore(&smgpio->lock, save); | ||
989 | |||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | static struct gpio_chip gpio_chip_template = { | ||
994 | .ngpio = 32, | ||
995 | .direction_input = sm501_gpio_input, | ||
996 | .direction_output = sm501_gpio_output, | ||
997 | .set = sm501_gpio_set, | ||
998 | .get = sm501_gpio_get, | ||
999 | }; | ||
1000 | |||
1001 | static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm, | ||
1002 | struct sm501_gpio *gpio, | ||
1003 | struct sm501_gpio_chip *chip) | ||
1004 | { | ||
1005 | struct sm501_platdata *pdata = sm->platdata; | ||
1006 | struct gpio_chip *gchip = &chip->gpio; | ||
1007 | int base = pdata->gpio_base; | ||
1008 | |||
1009 | chip->gpio = gpio_chip_template; | ||
1010 | |||
1011 | if (chip == &gpio->high) { | ||
1012 | if (base > 0) | ||
1013 | base += 32; | ||
1014 | chip->regbase = gpio->regs + SM501_GPIO_DATA_HIGH; | ||
1015 | gchip->label = "SM501-HIGH"; | ||
1016 | } else { | ||
1017 | chip->regbase = gpio->regs + SM501_GPIO_DATA_LOW; | ||
1018 | gchip->label = "SM501-LOW"; | ||
1019 | } | ||
1020 | |||
1021 | gchip->base = base; | ||
1022 | chip->ourgpio = gpio; | ||
1023 | |||
1024 | return gpiochip_add(gchip); | ||
1025 | } | ||
1026 | |||
1027 | static int sm501_register_gpio(struct sm501_devdata *sm) | ||
1028 | { | ||
1029 | struct sm501_gpio *gpio = &sm->gpio; | ||
1030 | resource_size_t iobase = sm->io_res->start + SM501_GPIO; | ||
1031 | int ret; | ||
1032 | int tmp; | ||
1033 | |||
1034 | dev_dbg(sm->dev, "registering gpio block %08llx\n", | ||
1035 | (unsigned long long)iobase); | ||
1036 | |||
1037 | spin_lock_init(&gpio->lock); | ||
1038 | |||
1039 | gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio"); | ||
1040 | if (gpio->regs_res == NULL) { | ||
1041 | dev_err(sm->dev, "gpio: failed to request region\n"); | ||
1042 | return -ENXIO; | ||
1043 | } | ||
1044 | |||
1045 | gpio->regs = ioremap(iobase, 0x20); | ||
1046 | if (gpio->regs == NULL) { | ||
1047 | dev_err(sm->dev, "gpio: failed to remap registers\n"); | ||
1048 | ret = -ENXIO; | ||
1049 | goto err_claimed; | ||
1050 | } | ||
1051 | |||
1052 | /* Register both our chips. */ | ||
1053 | |||
1054 | ret = sm501_gpio_register_chip(sm, gpio, &gpio->low); | ||
1055 | if (ret) { | ||
1056 | dev_err(sm->dev, "failed to add low chip\n"); | ||
1057 | goto err_mapped; | ||
1058 | } | ||
1059 | |||
1060 | ret = sm501_gpio_register_chip(sm, gpio, &gpio->high); | ||
1061 | if (ret) { | ||
1062 | dev_err(sm->dev, "failed to add high chip\n"); | ||
1063 | goto err_low_chip; | ||
1064 | } | ||
1065 | |||
1066 | gpio->registered = 1; | ||
1067 | |||
1068 | return 0; | ||
1069 | |||
1070 | err_low_chip: | ||
1071 | tmp = gpiochip_remove(&gpio->low.gpio); | ||
1072 | if (tmp) { | ||
1073 | dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n"); | ||
1074 | return ret; | ||
1075 | } | ||
1076 | |||
1077 | err_mapped: | ||
1078 | iounmap(gpio->regs); | ||
1079 | |||
1080 | err_claimed: | ||
1081 | release_resource(gpio->regs_res); | ||
1082 | kfree(gpio->regs_res); | ||
1083 | |||
1084 | return ret; | ||
1085 | } | ||
1086 | |||
1087 | static void sm501_gpio_remove(struct sm501_devdata *sm) | ||
1088 | { | ||
1089 | struct sm501_gpio *gpio = &sm->gpio; | ||
1090 | int ret; | ||
1091 | |||
1092 | if (!sm->gpio.registered) | ||
1093 | return; | ||
1094 | |||
1095 | ret = gpiochip_remove(&gpio->low.gpio); | ||
1096 | if (ret) | ||
1097 | dev_err(sm->dev, "cannot remove low chip, cannot tidy up\n"); | ||
1098 | |||
1099 | ret = gpiochip_remove(&gpio->high.gpio); | ||
1100 | if (ret) | ||
1101 | dev_err(sm->dev, "cannot remove high chip, cannot tidy up\n"); | ||
1102 | |||
1103 | iounmap(gpio->regs); | ||
1104 | release_resource(gpio->regs_res); | ||
1105 | kfree(gpio->regs_res); | ||
1106 | } | ||
1107 | |||
1108 | static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) | ||
1109 | { | ||
1110 | struct sm501_gpio *gpio = &sm->gpio; | ||
1111 | int base = (pin < 32) ? gpio->low.gpio.base : gpio->high.gpio.base; | ||
1112 | |||
1113 | return (pin % 32) + base; | ||
1114 | } | ||
1115 | |||
1116 | static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) | ||
1117 | { | ||
1118 | return sm->gpio.registered; | ||
1119 | } | ||
1120 | #else | ||
1121 | static inline int sm501_register_gpio(struct sm501_devdata *sm) | ||
1122 | { | ||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1126 | static inline void sm501_gpio_remove(struct sm501_devdata *sm) | ||
1127 | { | ||
1128 | } | ||
1129 | |||
1130 | static inline int sm501_gpio_pin2nr(struct sm501_devdata *sm, unsigned int pin) | ||
1131 | { | ||
1132 | return -1; | ||
1133 | } | ||
1134 | |||
1135 | static inline int sm501_gpio_isregistered(struct sm501_devdata *sm) | ||
1136 | { | ||
1137 | return 0; | ||
1138 | } | ||
1139 | #endif | ||
1140 | |||
1141 | static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm, | ||
1142 | struct sm501_platdata_gpio_i2c *iic) | ||
1143 | { | ||
1144 | struct i2c_gpio_platform_data *icd; | ||
1145 | struct platform_device *pdev; | ||
1146 | |||
1147 | pdev = sm501_create_subdev(sm, "i2c-gpio", 0, | ||
1148 | sizeof(struct i2c_gpio_platform_data)); | ||
1149 | if (!pdev) | ||
1150 | return -ENOMEM; | ||
1151 | |||
1152 | icd = pdev->dev.platform_data; | ||
1153 | |||
1154 | /* We keep the pin_sda and pin_scl fields relative in case the | ||
1155 | * same platform data is passed to >1 SM501. | ||
1156 | */ | ||
1157 | |||
1158 | icd->sda_pin = sm501_gpio_pin2nr(sm, iic->pin_sda); | ||
1159 | icd->scl_pin = sm501_gpio_pin2nr(sm, iic->pin_scl); | ||
1160 | icd->timeout = iic->timeout; | ||
1161 | icd->udelay = iic->udelay; | ||
1162 | |||
1163 | /* note, we can't use either of the pin numbers, as the i2c-gpio | ||
1164 | * driver uses the platform.id field to generate the bus number | ||
1165 | * to register with the i2c core; The i2c core doesn't have enough | ||
1166 | * entries to deal with anything we currently use. | ||
1167 | */ | ||
1168 | |||
1169 | pdev->id = iic->bus_num; | ||
1170 | |||
1171 | dev_info(sm->dev, "registering i2c-%d: sda=%d (%d), scl=%d (%d)\n", | ||
1172 | iic->bus_num, | ||
1173 | icd->sda_pin, iic->pin_sda, icd->scl_pin, iic->pin_scl); | ||
1174 | |||
1175 | return sm501_register_device(sm, pdev); | ||
1176 | } | ||
1177 | |||
1178 | static int sm501_register_gpio_i2c(struct sm501_devdata *sm, | ||
1179 | struct sm501_platdata *pdata) | ||
1180 | { | ||
1181 | struct sm501_platdata_gpio_i2c *iic = pdata->gpio_i2c; | ||
1182 | int index; | ||
1183 | int ret; | ||
1184 | |||
1185 | for (index = 0; index < pdata->gpio_i2c_nr; index++, iic++) { | ||
1186 | ret = sm501_register_gpio_i2c_instance(sm, iic); | ||
1187 | if (ret < 0) | ||
1188 | return ret; | ||
1189 | } | ||
1190 | |||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
909 | /* sm501_dbg_regs | 1194 | /* sm501_dbg_regs |
910 | * | 1195 | * |
911 | * Debug attribute to attach to parent device to show core registers | 1196 | * Debug attribute to attach to parent device to show core registers |
@@ -1013,6 +1298,7 @@ static unsigned int sm501_mem_local[] = { | |||
1013 | static int sm501_init_dev(struct sm501_devdata *sm) | 1298 | static int sm501_init_dev(struct sm501_devdata *sm) |
1014 | { | 1299 | { |
1015 | struct sm501_initdata *idata; | 1300 | struct sm501_initdata *idata; |
1301 | struct sm501_platdata *pdata; | ||
1016 | resource_size_t mem_avail; | 1302 | resource_size_t mem_avail; |
1017 | unsigned long dramctrl; | 1303 | unsigned long dramctrl; |
1018 | unsigned long devid; | 1304 | unsigned long devid; |
@@ -1051,7 +1337,9 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
1051 | 1337 | ||
1052 | /* check to see if we have some device initialisation */ | 1338 | /* check to see if we have some device initialisation */ |
1053 | 1339 | ||
1054 | idata = sm->platdata ? sm->platdata->init : NULL; | 1340 | pdata = sm->platdata; |
1341 | idata = pdata ? pdata->init : NULL; | ||
1342 | |||
1055 | if (idata) { | 1343 | if (idata) { |
1056 | sm501_init_regs(sm, idata); | 1344 | sm501_init_regs(sm, idata); |
1057 | 1345 | ||
@@ -1059,6 +1347,15 @@ static int sm501_init_dev(struct sm501_devdata *sm) | |||
1059 | sm501_register_usbhost(sm, &mem_avail); | 1347 | sm501_register_usbhost(sm, &mem_avail); |
1060 | if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1)) | 1348 | if (idata->devices & (SM501_USE_UART0 | SM501_USE_UART1)) |
1061 | sm501_register_uart(sm, idata->devices); | 1349 | sm501_register_uart(sm, idata->devices); |
1350 | if (idata->devices & SM501_USE_GPIO) | ||
1351 | sm501_register_gpio(sm); | ||
1352 | } | ||
1353 | |||
1354 | if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) { | ||
1355 | if (!sm501_gpio_isregistered(sm)) | ||
1356 | dev_err(sm->dev, "no gpio available for i2c gpio.\n"); | ||
1357 | else | ||
1358 | sm501_register_gpio_i2c(sm, pdata); | ||
1062 | } | 1359 | } |
1063 | 1360 | ||
1064 | ret = sm501_check_clocks(sm); | 1361 | ret = sm501_check_clocks(sm); |
@@ -1138,8 +1435,31 @@ static int sm501_plat_probe(struct platform_device *dev) | |||
1138 | } | 1435 | } |
1139 | 1436 | ||
1140 | #ifdef CONFIG_PM | 1437 | #ifdef CONFIG_PM |
1438 | |||
1141 | /* power management support */ | 1439 | /* power management support */ |
1142 | 1440 | ||
1441 | static void sm501_set_power(struct sm501_devdata *sm, int on) | ||
1442 | { | ||
1443 | struct sm501_platdata *pd = sm->platdata; | ||
1444 | |||
1445 | if (pd == NULL) | ||
1446 | return; | ||
1447 | |||
1448 | if (pd->get_power) { | ||
1449 | if (pd->get_power(sm->dev) == on) { | ||
1450 | dev_dbg(sm->dev, "is already %d\n", on); | ||
1451 | return; | ||
1452 | } | ||
1453 | } | ||
1454 | |||
1455 | if (pd->set_power) { | ||
1456 | dev_dbg(sm->dev, "setting power to %d\n", on); | ||
1457 | |||
1458 | pd->set_power(sm->dev, on); | ||
1459 | sm501_mdelay(sm, 10); | ||
1460 | } | ||
1461 | } | ||
1462 | |||
1143 | static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) | 1463 | static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) |
1144 | { | 1464 | { |
1145 | struct sm501_devdata *sm = platform_get_drvdata(pdev); | 1465 | struct sm501_devdata *sm = platform_get_drvdata(pdev); |
@@ -1148,6 +1468,12 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state) | |||
1148 | sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL); | 1468 | sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL); |
1149 | 1469 | ||
1150 | sm501_dump_regs(sm); | 1470 | sm501_dump_regs(sm); |
1471 | |||
1472 | if (sm->platdata) { | ||
1473 | if (sm->platdata->flags & SM501_FLAG_SUSPEND_OFF) | ||
1474 | sm501_set_power(sm, 0); | ||
1475 | } | ||
1476 | |||
1151 | return 0; | 1477 | return 0; |
1152 | } | 1478 | } |
1153 | 1479 | ||
@@ -1155,6 +1481,8 @@ static int sm501_plat_resume(struct platform_device *pdev) | |||
1155 | { | 1481 | { |
1156 | struct sm501_devdata *sm = platform_get_drvdata(pdev); | 1482 | struct sm501_devdata *sm = platform_get_drvdata(pdev); |
1157 | 1483 | ||
1484 | sm501_set_power(sm, 1); | ||
1485 | |||
1158 | sm501_dump_regs(sm); | 1486 | sm501_dump_regs(sm); |
1159 | sm501_dump_gate(sm); | 1487 | sm501_dump_gate(sm); |
1160 | sm501_dump_clk(sm); | 1488 | sm501_dump_clk(sm); |
@@ -1229,6 +1557,7 @@ static struct sm501_platdata_fb sm501_fb_pdata = { | |||
1229 | static struct sm501_platdata sm501_pci_platdata = { | 1557 | static struct sm501_platdata sm501_pci_platdata = { |
1230 | .init = &sm501_pci_initdata, | 1558 | .init = &sm501_pci_initdata, |
1231 | .fb = &sm501_fb_pdata, | 1559 | .fb = &sm501_fb_pdata, |
1560 | .gpio_base = -1, | ||
1232 | }; | 1561 | }; |
1233 | 1562 | ||
1234 | static int sm501_pci_probe(struct pci_dev *dev, | 1563 | static int sm501_pci_probe(struct pci_dev *dev, |
@@ -1335,6 +1664,8 @@ static void sm501_dev_remove(struct sm501_devdata *sm) | |||
1335 | sm501_remove_sub(sm, smdev); | 1664 | sm501_remove_sub(sm, smdev); |
1336 | 1665 | ||
1337 | device_remove_file(sm->dev, &dev_attr_dbg_regs); | 1666 | device_remove_file(sm->dev, &dev_attr_dbg_regs); |
1667 | |||
1668 | sm501_gpio_remove(sm); | ||
1338 | } | 1669 | } |
1339 | 1670 | ||
1340 | static void sm501_pci_remove(struct pci_dev *dev) | 1671 | static void sm501_pci_remove(struct pci_dev *dev) |
@@ -1378,6 +1709,8 @@ static struct pci_driver sm501_pci_drv = { | |||
1378 | .remove = sm501_pci_remove, | 1709 | .remove = sm501_pci_remove, |
1379 | }; | 1710 | }; |
1380 | 1711 | ||
1712 | MODULE_ALIAS("platform:sm501"); | ||
1713 | |||
1381 | static struct platform_driver sm501_plat_drv = { | 1714 | static struct platform_driver sm501_plat_drv = { |
1382 | .driver = { | 1715 | .driver = { |
1383 | .name = "sm501", | 1716 | .name = "sm501", |