diff options
| -rw-r--r-- | drivers/mfd/Kconfig | 24 | ||||
| -rw-r--r-- | drivers/mfd/Makefile | 5 | ||||
| -rw-r--r-- | drivers/mfd/ab3100-core.c | 991 | ||||
| -rw-r--r-- | drivers/mfd/asic3.c | 312 | ||||
| -rw-r--r-- | drivers/mfd/da903x.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/ezx-pcap.c | 505 | ||||
| -rw-r--r-- | drivers/mfd/pcf50633-core.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/pcf50633-gpio.c | 3 | ||||
| -rw-r--r-- | drivers/mfd/t7l66xb.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/tc6387xb.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/tc6393xb.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/twl4030-core.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/twl4030-irq.c | 2 | ||||
| -rw-r--r-- | drivers/mfd/wm8350-regmap.c | 4 | ||||
| -rw-r--r-- | drivers/mfd/wm8400-core.c | 2 | ||||
| -rw-r--r-- | include/linux/mfd/ab3100.h | 103 | ||||
| -rw-r--r-- | include/linux/mfd/asic3.h | 236 | ||||
| -rw-r--r-- | include/linux/mfd/ezx-pcap.h | 256 | ||||
| -rw-r--r-- | include/linux/mfd/tmio.h | 2 |
19 files changed, 2219 insertions, 238 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index ee3927ab11e0..491ac0f800d2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
| @@ -30,6 +30,7 @@ config MFD_SM501_GPIO | |||
| 30 | config MFD_ASIC3 | 30 | config MFD_ASIC3 |
| 31 | bool "Support for Compaq ASIC3" | 31 | bool "Support for Compaq ASIC3" |
| 32 | depends on GENERIC_HARDIRQS && GPIOLIB && ARM | 32 | depends on GENERIC_HARDIRQS && GPIOLIB && ARM |
| 33 | select MFD_CORE | ||
| 33 | ---help--- | 34 | ---help--- |
| 34 | This driver supports the ASIC3 multifunction chip found on many | 35 | This driver supports the ASIC3 multifunction chip found on many |
| 35 | PDAs (mainly iPAQ and HTC based ones) | 36 | PDAs (mainly iPAQ and HTC based ones) |
| @@ -152,7 +153,7 @@ config MFD_WM8400 | |||
| 152 | depends on I2C | 153 | depends on I2C |
| 153 | help | 154 | help |
| 154 | Support for the Wolfson Microelecronics WM8400 PMIC and audio | 155 | Support for the Wolfson Microelecronics WM8400 PMIC and audio |
| 155 | CODEC. This driver adds provides common support for accessing | 156 | CODEC. This driver provides common support for accessing |
| 156 | the device, additional drivers must be enabled in order to use | 157 | the device, additional drivers must be enabled in order to use |
| 157 | the functionality of the device. | 158 | the functionality of the device. |
| 158 | 159 | ||
| @@ -241,6 +242,27 @@ config PCF50633_GPIO | |||
| 241 | Say yes here if you want to include support GPIO for pins on | 242 | Say yes here if you want to include support GPIO for pins on |
| 242 | the PCF50633 chip. | 243 | the PCF50633 chip. |
| 243 | 244 | ||
| 245 | config AB3100_CORE | ||
| 246 | tristate "ST-Ericsson AB3100 Mixed Signal Circuit core functions" | ||
| 247 | depends on I2C | ||
| 248 | default y if ARCH_U300 | ||
| 249 | help | ||
| 250 | Select this to enable the AB3100 Mixed Signal IC core | ||
| 251 | functionality. This connects to a AB3100 on the I2C bus | ||
| 252 | and expose a number of symbols needed for dependent devices | ||
| 253 | to read and write registers and subscribe to events from | ||
| 254 | this multi-functional IC. This is needed to use other features | ||
| 255 | of the AB3100 such as battery-backed RTC, charging control, | ||
| 256 | LEDs, vibrator, system power and temperature, power management | ||
| 257 | and ALSA sound. | ||
| 258 | |||
| 259 | config EZX_PCAP | ||
| 260 | bool "PCAP Support" | ||
| 261 | depends on GENERIC_HARDIRQS && SPI_MASTER | ||
| 262 | help | ||
| 263 | This enables the PCAP ASIC present on EZX Phones. This is | ||
| 264 | needed for MMC, TouchScreen, Sound, USB, etc.. | ||
| 265 | |||
| 244 | endmenu | 266 | endmenu |
| 245 | 267 | ||
| 246 | menu "Multimedia Capabilities Port drivers" | 268 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 3afb5192e4da..6f8a9a1af20b 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
| @@ -26,6 +26,8 @@ obj-$(CONFIG_TWL4030_CORE) += twl4030-core.o twl4030-irq.o | |||
| 26 | 26 | ||
| 27 | obj-$(CONFIG_MFD_CORE) += mfd-core.o | 27 | obj-$(CONFIG_MFD_CORE) += mfd-core.o |
| 28 | 28 | ||
| 29 | obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o | ||
| 30 | |||
| 29 | obj-$(CONFIG_MCP) += mcp-core.o | 31 | obj-$(CONFIG_MCP) += mcp-core.o |
| 30 | obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o | 32 | obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o |
| 31 | obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o | 33 | obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o |
| @@ -40,4 +42,5 @@ obj-$(CONFIG_PMIC_DA903X) += da903x.o | |||
| 40 | 42 | ||
| 41 | obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o | 43 | obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o |
| 42 | obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o | 44 | obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o |
| 43 | obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o \ No newline at end of file | 45 | obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o |
| 46 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | ||
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c new file mode 100644 index 000000000000..13e7d7bfe85f --- /dev/null +++ b/drivers/mfd/ab3100-core.c | |||
| @@ -0,0 +1,991 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2009 ST-Ericsson | ||
| 3 | * License terms: GNU General Public License (GPL) version 2 | ||
| 4 | * Low-level core for exclusive access to the AB3100 IC on the I2C bus | ||
| 5 | * and some basic chip-configuration. | ||
| 6 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/i2c.h> | ||
| 10 | #include <linux/mutex.h> | ||
| 11 | #include <linux/list.h> | ||
| 12 | #include <linux/notifier.h> | ||
| 13 | #include <linux/err.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/workqueue.h> | ||
| 18 | #include <linux/debugfs.h> | ||
| 19 | #include <linux/seq_file.h> | ||
| 20 | #include <linux/uaccess.h> | ||
| 21 | #include <linux/mfd/ab3100.h> | ||
| 22 | |||
| 23 | /* These are the only registers inside AB3100 used in this main file */ | ||
| 24 | |||
| 25 | /* Interrupt event registers */ | ||
| 26 | #define AB3100_EVENTA1 0x21 | ||
| 27 | #define AB3100_EVENTA2 0x22 | ||
| 28 | #define AB3100_EVENTA3 0x23 | ||
| 29 | |||
| 30 | /* AB3100 DAC converter registers */ | ||
| 31 | #define AB3100_DIS 0x00 | ||
| 32 | #define AB3100_D0C 0x01 | ||
| 33 | #define AB3100_D1C 0x02 | ||
| 34 | #define AB3100_D2C 0x03 | ||
| 35 | #define AB3100_D3C 0x04 | ||
| 36 | |||
| 37 | /* Chip ID register */ | ||
| 38 | #define AB3100_CID 0x20 | ||
| 39 | |||
| 40 | /* AB3100 interrupt registers */ | ||
| 41 | #define AB3100_IMRA1 0x24 | ||
| 42 | #define AB3100_IMRA2 0x25 | ||
| 43 | #define AB3100_IMRA3 0x26 | ||
| 44 | #define AB3100_IMRB1 0x2B | ||
| 45 | #define AB3100_IMRB2 0x2C | ||
| 46 | #define AB3100_IMRB3 0x2D | ||
| 47 | |||
| 48 | /* System Power Monitoring and control registers */ | ||
| 49 | #define AB3100_MCA 0x2E | ||
| 50 | #define AB3100_MCB 0x2F | ||
| 51 | |||
| 52 | /* SIM power up */ | ||
| 53 | #define AB3100_SUP 0x50 | ||
| 54 | |||
| 55 | /* | ||
| 56 | * I2C communication | ||
| 57 | * | ||
| 58 | * The AB3100 is usually assigned address 0x48 (7-bit) | ||
| 59 | * The chip is defined in the platform i2c_board_data section. | ||
| 60 | */ | ||
| 61 | static unsigned short normal_i2c[] = { 0x48, I2C_CLIENT_END }; | ||
| 62 | I2C_CLIENT_INSMOD_1(ab3100); | ||
| 63 | |||
| 64 | u8 ab3100_get_chip_type(struct ab3100 *ab3100) | ||
| 65 | { | ||
| 66 | u8 chip = ABUNKNOWN; | ||
| 67 | |||
| 68 | switch (ab3100->chip_id & 0xf0) { | ||
| 69 | case 0xa0: | ||
| 70 | chip = AB3000; | ||
| 71 | break; | ||
| 72 | case 0xc0: | ||
| 73 | chip = AB3100; | ||
| 74 | break; | ||
| 75 | } | ||
| 76 | return chip; | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL(ab3100_get_chip_type); | ||
| 79 | |||
| 80 | int ab3100_set_register(struct ab3100 *ab3100, u8 reg, u8 regval) | ||
| 81 | { | ||
| 82 | u8 regandval[2] = {reg, regval}; | ||
| 83 | int err; | ||
| 84 | |||
| 85 | err = mutex_lock_interruptible(&ab3100->access_mutex); | ||
| 86 | if (err) | ||
| 87 | return err; | ||
| 88 | |||
| 89 | /* | ||
| 90 | * A two-byte write message with the first byte containing the register | ||
| 91 | * number and the second byte containing the value to be written | ||
| 92 | * effectively sets a register in the AB3100. | ||
| 93 | */ | ||
| 94 | err = i2c_master_send(ab3100->i2c_client, regandval, 2); | ||
| 95 | if (err < 0) { | ||
| 96 | dev_err(ab3100->dev, | ||
| 97 | "write error (write register): %d\n", | ||
| 98 | err); | ||
| 99 | } else if (err != 2) { | ||
| 100 | dev_err(ab3100->dev, | ||
| 101 | "write error (write register) " | ||
| 102 | "%d bytes transferred (expected 2)\n", | ||
| 103 | err); | ||
| 104 | err = -EIO; | ||
| 105 | } else { | ||
| 106 | /* All is well */ | ||
| 107 | err = 0; | ||
| 108 | } | ||
| 109 | mutex_unlock(&ab3100->access_mutex); | ||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | EXPORT_SYMBOL(ab3100_set_register); | ||
| 113 | |||
| 114 | /* | ||
| 115 | * The test registers exist at an I2C bus address up one | ||
| 116 | * from the ordinary base. They are not supposed to be used | ||
| 117 | * in production code, but sometimes you have to do that | ||
| 118 | * anyway. It's currently only used from this file so declare | ||
| 119 | * it static and do not export. | ||
| 120 | */ | ||
| 121 | static int ab3100_set_test_register(struct ab3100 *ab3100, | ||
| 122 | u8 reg, u8 regval) | ||
| 123 | { | ||
| 124 | u8 regandval[2] = {reg, regval}; | ||
| 125 | int err; | ||
| 126 | |||
| 127 | err = mutex_lock_interruptible(&ab3100->access_mutex); | ||
| 128 | if (err) | ||
| 129 | return err; | ||
| 130 | |||
| 131 | err = i2c_master_send(ab3100->testreg_client, regandval, 2); | ||
| 132 | if (err < 0) { | ||
| 133 | dev_err(ab3100->dev, | ||
| 134 | "write error (write test register): %d\n", | ||
| 135 | err); | ||
| 136 | } else if (err != 2) { | ||
| 137 | dev_err(ab3100->dev, | ||
| 138 | "write error (write test register) " | ||
| 139 | "%d bytes transferred (expected 2)\n", | ||
| 140 | err); | ||
| 141 | err = -EIO; | ||
| 142 | } else { | ||
| 143 | /* All is well */ | ||
| 144 | err = 0; | ||
| 145 | } | ||
| 146 | mutex_unlock(&ab3100->access_mutex); | ||
| 147 | |||
| 148 | return err; | ||
| 149 | } | ||
| 150 | |||
| 151 | int ab3100_get_register(struct ab3100 *ab3100, u8 reg, u8 *regval) | ||
| 152 | { | ||
| 153 | int err; | ||
| 154 | |||
| 155 | err = mutex_lock_interruptible(&ab3100->access_mutex); | ||
| 156 | if (err) | ||
| 157 | return err; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * AB3100 require an I2C "stop" command between each message, else | ||
| 161 | * it will not work. The only way of achieveing this with the | ||
| 162 | * message transport layer is to send the read and write messages | ||
| 163 | * separately. | ||
| 164 | */ | ||
| 165 | err = i2c_master_send(ab3100->i2c_client, ®, 1); | ||
| 166 | if (err < 0) { | ||
| 167 | dev_err(ab3100->dev, | ||
| 168 | "write error (send register address): %d\n", | ||
| 169 | err); | ||
| 170 | goto get_reg_out_unlock; | ||
| 171 | } else if (err != 1) { | ||
| 172 | dev_err(ab3100->dev, | ||
| 173 | "write error (send register address) " | ||
| 174 | "%d bytes transferred (expected 1)\n", | ||
| 175 | err); | ||
| 176 | err = -EIO; | ||
| 177 | goto get_reg_out_unlock; | ||
| 178 | } else { | ||
| 179 | /* All is well */ | ||
| 180 | err = 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | err = i2c_master_recv(ab3100->i2c_client, regval, 1); | ||
| 184 | if (err < 0) { | ||
| 185 | dev_err(ab3100->dev, | ||
| 186 | "write error (read register): %d\n", | ||
| 187 | err); | ||
| 188 | goto get_reg_out_unlock; | ||
| 189 | } else if (err != 1) { | ||
| 190 | dev_err(ab3100->dev, | ||
| 191 | "write error (read register) " | ||
| 192 | "%d bytes transferred (expected 1)\n", | ||
| 193 | err); | ||
| 194 | err = -EIO; | ||
| 195 | goto get_reg_out_unlock; | ||
| 196 | } else { | ||
| 197 | /* All is well */ | ||
| 198 | err = 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | get_reg_out_unlock: | ||
| 202 | mutex_unlock(&ab3100->access_mutex); | ||
| 203 | return err; | ||
| 204 | } | ||
| 205 | EXPORT_SYMBOL(ab3100_get_register); | ||
| 206 | |||
| 207 | int ab3100_get_register_page(struct ab3100 *ab3100, | ||
| 208 | u8 first_reg, u8 *regvals, u8 numregs) | ||
| 209 | { | ||
| 210 | int err; | ||
| 211 | |||
| 212 | if (ab3100->chip_id == 0xa0 || | ||
| 213 | ab3100->chip_id == 0xa1) | ||
| 214 | /* These don't support paged reads */ | ||
| 215 | return -EIO; | ||
| 216 | |||
| 217 | err = mutex_lock_interruptible(&ab3100->access_mutex); | ||
| 218 | if (err) | ||
| 219 | return err; | ||
| 220 | |||
| 221 | /* | ||
| 222 | * Paged read also require an I2C "stop" command. | ||
| 223 | */ | ||
| 224 | err = i2c_master_send(ab3100->i2c_client, &first_reg, 1); | ||
| 225 | if (err < 0) { | ||
| 226 | dev_err(ab3100->dev, | ||
| 227 | "write error (send first register address): %d\n", | ||
| 228 | err); | ||
| 229 | goto get_reg_page_out_unlock; | ||
| 230 | } else if (err != 1) { | ||
| 231 | dev_err(ab3100->dev, | ||
| 232 | "write error (send first register address) " | ||
| 233 | "%d bytes transferred (expected 1)\n", | ||
| 234 | err); | ||
| 235 | err = -EIO; | ||
| 236 | goto get_reg_page_out_unlock; | ||
| 237 | } | ||
| 238 | |||
| 239 | err = i2c_master_recv(ab3100->i2c_client, regvals, numregs); | ||
| 240 | if (err < 0) { | ||
| 241 | dev_err(ab3100->dev, | ||
| 242 | "write error (read register page): %d\n", | ||
| 243 | err); | ||
| 244 | goto get_reg_page_out_unlock; | ||
| 245 | } else if (err != numregs) { | ||
| 246 | dev_err(ab3100->dev, | ||
| 247 | "write error (read register page) " | ||
| 248 | "%d bytes transferred (expected %d)\n", | ||
| 249 | err, numregs); | ||
| 250 | err = -EIO; | ||
| 251 | goto get_reg_page_out_unlock; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* All is well */ | ||
| 255 | err = 0; | ||
| 256 | |||
| 257 | get_reg_page_out_unlock: | ||
| 258 | mutex_unlock(&ab3100->access_mutex); | ||
| 259 | return err; | ||
| 260 | } | ||
| 261 | EXPORT_SYMBOL(ab3100_get_register_page); | ||
| 262 | |||
| 263 | int ab3100_mask_and_set_register(struct ab3100 *ab3100, | ||
| 264 | u8 reg, u8 andmask, u8 ormask) | ||
| 265 | { | ||
| 266 | u8 regandval[2] = {reg, 0}; | ||
| 267 | int err; | ||
| 268 | |||
| 269 | err = mutex_lock_interruptible(&ab3100->access_mutex); | ||
| 270 | if (err) | ||
| 271 | return err; | ||
| 272 | |||
| 273 | /* First read out the target register */ | ||
| 274 | err = i2c_master_send(ab3100->i2c_client, ®, 1); | ||
| 275 | if (err < 0) { | ||
| 276 | dev_err(ab3100->dev, | ||
| 277 | "write error (maskset send address): %d\n", | ||
| 278 | err); | ||
| 279 | goto get_maskset_unlock; | ||
| 280 | } else if (err != 1) { | ||
| 281 | dev_err(ab3100->dev, | ||
| 282 | "write error (maskset send address) " | ||
| 283 | "%d bytes transferred (expected 1)\n", | ||
| 284 | err); | ||
| 285 | err = -EIO; | ||
| 286 | goto get_maskset_unlock; | ||
| 287 | } | ||
| 288 | |||
| 289 | err = i2c_master_recv(ab3100->i2c_client, ®andval[1], 1); | ||
| 290 | if (err < 0) { | ||
| 291 | dev_err(ab3100->dev, | ||
| 292 | "write error (maskset read register): %d\n", | ||
| 293 | err); | ||
| 294 | goto get_maskset_unlock; | ||
| 295 | } else if (err != 1) { | ||
| 296 | dev_err(ab3100->dev, | ||
| 297 | "write error (maskset read register) " | ||
| 298 | "%d bytes transferred (expected 1)\n", | ||
| 299 | err); | ||
| 300 | err = -EIO; | ||
| 301 | goto get_maskset_unlock; | ||
| 302 | } | ||
| 303 | |||
| 304 | /* Modify the register */ | ||
| 305 | regandval[1] &= andmask; | ||
| 306 | regandval[1] |= ormask; | ||
| 307 | |||
| 308 | /* Write the register */ | ||
| 309 | err = i2c_master_send(ab3100->i2c_client, regandval, 2); | ||
| 310 | if (err < 0) { | ||
| 311 | dev_err(ab3100->dev, | ||
| 312 | "write error (write register): %d\n", | ||
| 313 | err); | ||
| 314 | goto get_maskset_unlock; | ||
| 315 | } else if (err != 2) { | ||
| 316 | dev_err(ab3100->dev, | ||
| 317 | "write error (write register) " | ||
| 318 | "%d bytes transferred (expected 2)\n", | ||
| 319 | err); | ||
| 320 | err = -EIO; | ||
| 321 | goto get_maskset_unlock; | ||
| 322 | } | ||
| 323 | |||
| 324 | /* All is well */ | ||
| 325 | err = 0; | ||
| 326 | |||
| 327 | get_maskset_unlock: | ||
| 328 | mutex_unlock(&ab3100->access_mutex); | ||
| 329 | return err; | ||
| 330 | } | ||
| 331 | EXPORT_SYMBOL(ab3100_mask_and_set_register); | ||
| 332 | |||
| 333 | /* | ||
| 334 | * Register a simple callback for handling any AB3100 events. | ||
| 335 | */ | ||
| 336 | int ab3100_event_register(struct ab3100 *ab3100, | ||
| 337 | struct notifier_block *nb) | ||
| 338 | { | ||
| 339 | return blocking_notifier_chain_register(&ab3100->event_subscribers, | ||
| 340 | nb); | ||
| 341 | } | ||
| 342 | EXPORT_SYMBOL(ab3100_event_register); | ||
| 343 | |||
| 344 | /* | ||
| 345 | * Remove a previously registered callback. | ||
| 346 | */ | ||
| 347 | int ab3100_event_unregister(struct ab3100 *ab3100, | ||
| 348 | struct notifier_block *nb) | ||
| 349 | { | ||
| 350 | return blocking_notifier_chain_unregister(&ab3100->event_subscribers, | ||
| 351 | nb); | ||
| 352 | } | ||
| 353 | EXPORT_SYMBOL(ab3100_event_unregister); | ||
| 354 | |||
| 355 | |||
| 356 | int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100, | ||
| 357 | u32 *fatevent) | ||
| 358 | { | ||
| 359 | if (!ab3100->startup_events_read) | ||
| 360 | return -EAGAIN; /* Try again later */ | ||
| 361 | *fatevent = ab3100->startup_events; | ||
| 362 | return 0; | ||
| 363 | } | ||
| 364 | EXPORT_SYMBOL(ab3100_event_registers_startup_state_get); | ||
| 365 | |||
| 366 | /* Interrupt handling worker */ | ||
| 367 | static void ab3100_work(struct work_struct *work) | ||
| 368 | { | ||
| 369 | struct ab3100 *ab3100 = container_of(work, struct ab3100, work); | ||
| 370 | u8 event_regs[3]; | ||
| 371 | u32 fatevent; | ||
| 372 | int err; | ||
| 373 | |||
| 374 | err = ab3100_get_register_page(ab3100, AB3100_EVENTA1, | ||
| 375 | event_regs, 3); | ||
| 376 | if (err) | ||
| 377 | goto err_event_wq; | ||
| 378 | |||
| 379 | fatevent = (event_regs[0] << 16) | | ||
| 380 | (event_regs[1] << 8) | | ||
| 381 | event_regs[2]; | ||
| 382 | |||
| 383 | if (!ab3100->startup_events_read) { | ||
| 384 | ab3100->startup_events = fatevent; | ||
| 385 | ab3100->startup_events_read = true; | ||
| 386 | } | ||
| 387 | /* | ||
| 388 | * The notified parties will have to mask out the events | ||
| 389 | * they're interested in and react to them. They will be | ||
| 390 | * notified on all events, then they use the fatevent value | ||
| 391 | * to determine if they're interested. | ||
| 392 | */ | ||
| 393 | blocking_notifier_call_chain(&ab3100->event_subscribers, | ||
| 394 | fatevent, NULL); | ||
| 395 | |||
| 396 | dev_dbg(ab3100->dev, | ||
| 397 | "IRQ Event: 0x%08x\n", fatevent); | ||
| 398 | |||
| 399 | /* By now the IRQ should be acked and deasserted so enable it again */ | ||
| 400 | enable_irq(ab3100->i2c_client->irq); | ||
| 401 | return; | ||
| 402 | |||
| 403 | err_event_wq: | ||
| 404 | dev_dbg(ab3100->dev, | ||
| 405 | "error in event workqueue\n"); | ||
| 406 | /* Enable the IRQ anyway, what choice do we have? */ | ||
| 407 | enable_irq(ab3100->i2c_client->irq); | ||
| 408 | return; | ||
| 409 | } | ||
| 410 | |||
| 411 | static irqreturn_t ab3100_irq_handler(int irq, void *data) | ||
| 412 | { | ||
| 413 | struct ab3100 *ab3100 = data; | ||
| 414 | /* | ||
| 415 | * Disable the IRQ and dispatch a worker to handle the | ||
| 416 | * event. Since the chip resides on I2C this is slow | ||
| 417 | * stuff and we will re-enable the interrupts once th | ||
| 418 | * worker has finished. | ||
| 419 | */ | ||
| 420 | disable_irq(ab3100->i2c_client->irq); | ||
| 421 | schedule_work(&ab3100->work); | ||
| 422 | return IRQ_HANDLED; | ||
| 423 | } | ||
| 424 | |||
| 425 | #ifdef CONFIG_DEBUG_FS | ||
| 426 | /* | ||
| 427 | * Some debugfs entries only exposed if we're using debug | ||
| 428 | */ | ||
| 429 | static int ab3100_registers_print(struct seq_file *s, void *p) | ||
| 430 | { | ||
| 431 | struct ab3100 *ab3100 = s->private; | ||
| 432 | u8 value; | ||
| 433 | u8 reg; | ||
| 434 | |||
| 435 | seq_printf(s, "AB3100 registers:\n"); | ||
| 436 | |||
| 437 | for (reg = 0; reg < 0xff; reg++) { | ||
| 438 | ab3100_get_register(ab3100, reg, &value); | ||
| 439 | seq_printf(s, "[0x%x]: 0x%x\n", reg, value); | ||
| 440 | } | ||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | static int ab3100_registers_open(struct inode *inode, struct file *file) | ||
| 445 | { | ||
| 446 | return single_open(file, ab3100_registers_print, inode->i_private); | ||
| 447 | } | ||
| 448 | |||
| 449 | static const struct file_operations ab3100_registers_fops = { | ||
| 450 | .open = ab3100_registers_open, | ||
| 451 | .read = seq_read, | ||
| 452 | .llseek = seq_lseek, | ||
| 453 | .release = single_release, | ||
| 454 | .owner = THIS_MODULE, | ||
| 455 | }; | ||
| 456 | |||
| 457 | struct ab3100_get_set_reg_priv { | ||
| 458 | struct ab3100 *ab3100; | ||
| 459 | bool mode; | ||
| 460 | }; | ||
| 461 | |||
| 462 | static int ab3100_get_set_reg_open_file(struct inode *inode, struct file *file) | ||
| 463 | { | ||
| 464 | file->private_data = inode->i_private; | ||
| 465 | return 0; | ||
| 466 | } | ||
| 467 | |||
| 468 | static int ab3100_get_set_reg(struct file *file, | ||
| 469 | const char __user *user_buf, | ||
| 470 | size_t count, loff_t *ppos) | ||
| 471 | { | ||
| 472 | struct ab3100_get_set_reg_priv *priv = file->private_data; | ||
| 473 | struct ab3100 *ab3100 = priv->ab3100; | ||
| 474 | char buf[32]; | ||
| 475 | int buf_size; | ||
| 476 | int regp; | ||
| 477 | unsigned long user_reg; | ||
| 478 | int err; | ||
| 479 | int i = 0; | ||
| 480 | |||
| 481 | /* Get userspace string and assure termination */ | ||
| 482 | buf_size = min(count, (sizeof(buf)-1)); | ||
| 483 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 484 | return -EFAULT; | ||
| 485 | buf[buf_size] = 0; | ||
| 486 | |||
| 487 | /* | ||
| 488 | * The idea is here to parse a string which is either | ||
| 489 | * "0xnn" for reading a register, or "0xaa 0xbb" for | ||
| 490 | * writing 0xbb to the register 0xaa. First move past | ||
| 491 | * whitespace and then begin to parse the register. | ||
| 492 | */ | ||
| 493 | while ((i < buf_size) && (buf[i] == ' ')) | ||
| 494 | i++; | ||
| 495 | regp = i; | ||
| 496 | |||
| 497 | /* | ||
| 498 | * Advance pointer to end of string then terminate | ||
| 499 | * the register string. This is needed to satisfy | ||
| 500 | * the strict_strtoul() function. | ||
| 501 | */ | ||
| 502 | while ((i < buf_size) && (buf[i] != ' ')) | ||
| 503 | i++; | ||
| 504 | buf[i] = '\0'; | ||
| 505 | |||
| 506 | err = strict_strtoul(&buf[regp], 16, &user_reg); | ||
| 507 | if (err) | ||
| 508 | return err; | ||
| 509 | if (user_reg > 0xff) | ||
| 510 | return -EINVAL; | ||
| 511 | |||
| 512 | /* Either we read or we write a register here */ | ||
| 513 | if (!priv->mode) { | ||
| 514 | /* Reading */ | ||
| 515 | u8 reg = (u8) user_reg; | ||
| 516 | u8 regvalue; | ||
| 517 | |||
| 518 | ab3100_get_register(ab3100, reg, ®value); | ||
| 519 | |||
| 520 | dev_info(ab3100->dev, | ||
| 521 | "debug read AB3100 reg[0x%02x]: 0x%02x\n", | ||
| 522 | reg, regvalue); | ||
| 523 | } else { | ||
| 524 | int valp; | ||
| 525 | unsigned long user_value; | ||
| 526 | u8 reg = (u8) user_reg; | ||
| 527 | u8 value; | ||
| 528 | u8 regvalue; | ||
| 529 | |||
| 530 | /* | ||
| 531 | * Writing, we need some value to write to | ||
| 532 | * the register so keep parsing the string | ||
| 533 | * from userspace. | ||
| 534 | */ | ||
| 535 | i++; | ||
| 536 | while ((i < buf_size) && (buf[i] == ' ')) | ||
| 537 | i++; | ||
| 538 | valp = i; | ||
| 539 | while ((i < buf_size) && (buf[i] != ' ')) | ||
| 540 | i++; | ||
| 541 | buf[i] = '\0'; | ||
| 542 | |||
| 543 | err = strict_strtoul(&buf[valp], 16, &user_value); | ||
| 544 | if (err) | ||
| 545 | return err; | ||
| 546 | if (user_reg > 0xff) | ||
| 547 | return -EINVAL; | ||
| 548 | |||
| 549 | value = (u8) user_value; | ||
| 550 | ab3100_set_register(ab3100, reg, value); | ||
| 551 | ab3100_get_register(ab3100, reg, ®value); | ||
| 552 | |||
| 553 | dev_info(ab3100->dev, | ||
| 554 | "debug write reg[0x%02x] with 0x%02x, " | ||
| 555 | "after readback: 0x%02x\n", | ||
| 556 | reg, value, regvalue); | ||
| 557 | } | ||
| 558 | return buf_size; | ||
| 559 | } | ||
| 560 | |||
| 561 | static const struct file_operations ab3100_get_set_reg_fops = { | ||
| 562 | .open = ab3100_get_set_reg_open_file, | ||
| 563 | .write = ab3100_get_set_reg, | ||
| 564 | }; | ||
| 565 | |||
| 566 | static struct dentry *ab3100_dir; | ||
| 567 | static struct dentry *ab3100_reg_file; | ||
| 568 | static struct ab3100_get_set_reg_priv ab3100_get_priv; | ||
| 569 | static struct dentry *ab3100_get_reg_file; | ||
| 570 | static struct ab3100_get_set_reg_priv ab3100_set_priv; | ||
| 571 | static struct dentry *ab3100_set_reg_file; | ||
| 572 | |||
| 573 | static void ab3100_setup_debugfs(struct ab3100 *ab3100) | ||
| 574 | { | ||
| 575 | int err; | ||
| 576 | |||
| 577 | ab3100_dir = debugfs_create_dir("ab3100", NULL); | ||
| 578 | if (!ab3100_dir) | ||
| 579 | goto exit_no_debugfs; | ||
| 580 | |||
| 581 | ab3100_reg_file = debugfs_create_file("registers", | ||
| 582 | S_IRUGO, ab3100_dir, ab3100, | ||
| 583 | &ab3100_registers_fops); | ||
| 584 | if (!ab3100_reg_file) { | ||
| 585 | err = -ENOMEM; | ||
| 586 | goto exit_destroy_dir; | ||
| 587 | } | ||
| 588 | |||
| 589 | ab3100_get_priv.ab3100 = ab3100; | ||
| 590 | ab3100_get_priv.mode = false; | ||
| 591 | ab3100_get_reg_file = debugfs_create_file("get_reg", | ||
| 592 | S_IWUGO, ab3100_dir, &ab3100_get_priv, | ||
| 593 | &ab3100_get_set_reg_fops); | ||
| 594 | if (!ab3100_get_reg_file) { | ||
| 595 | err = -ENOMEM; | ||
| 596 | goto exit_destroy_reg; | ||
| 597 | } | ||
| 598 | |||
| 599 | ab3100_set_priv.ab3100 = ab3100; | ||
| 600 | ab3100_set_priv.mode = true; | ||
| 601 | ab3100_set_reg_file = debugfs_create_file("set_reg", | ||
| 602 | S_IWUGO, ab3100_dir, &ab3100_set_priv, | ||
| 603 | &ab3100_get_set_reg_fops); | ||
| 604 | if (!ab3100_set_reg_file) { | ||
| 605 | err = -ENOMEM; | ||
| 606 | goto exit_destroy_get_reg; | ||
| 607 | } | ||
| 608 | return; | ||
| 609 | |||
| 610 | exit_destroy_get_reg: | ||
| 611 | debugfs_remove(ab3100_get_reg_file); | ||
| 612 | exit_destroy_reg: | ||
| 613 | debugfs_remove(ab3100_reg_file); | ||
| 614 | exit_destroy_dir: | ||
| 615 | debugfs_remove(ab3100_dir); | ||
| 616 | exit_no_debugfs: | ||
| 617 | return; | ||
| 618 | } | ||
| 619 | static inline void ab3100_remove_debugfs(void) | ||
| 620 | { | ||
| 621 | debugfs_remove(ab3100_set_reg_file); | ||
| 622 | debugfs_remove(ab3100_get_reg_file); | ||
| 623 | debugfs_remove(ab3100_reg_file); | ||
| 624 | debugfs_remove(ab3100_dir); | ||
| 625 | } | ||
| 626 | #else | ||
| 627 | static inline void ab3100_setup_debugfs(struct ab3100 *ab3100) | ||
| 628 | { | ||
| 629 | } | ||
| 630 | static inline void ab3100_remove_debugfs(void) | ||
| 631 | { | ||
| 632 | } | ||
| 633 | #endif | ||
| 634 | |||
| 635 | /* | ||
| 636 | * Basic set-up, datastructure creation/destruction and I2C interface. | ||
| 637 | * This sets up a default config in the AB3100 chip so that it | ||
| 638 | * will work as expected. | ||
| 639 | */ | ||
| 640 | |||
| 641 | struct ab3100_init_setting { | ||
| 642 | u8 abreg; | ||
| 643 | u8 setting; | ||
| 644 | }; | ||
| 645 | |||
| 646 | static const struct ab3100_init_setting __initdata | ||
| 647 | ab3100_init_settings[] = { | ||
| 648 | { | ||
| 649 | .abreg = AB3100_MCA, | ||
| 650 | .setting = 0x01 | ||
| 651 | }, { | ||
| 652 | .abreg = AB3100_MCB, | ||
| 653 | .setting = 0x30 | ||
| 654 | }, { | ||
| 655 | .abreg = AB3100_IMRA1, | ||
| 656 | .setting = 0x00 | ||
| 657 | }, { | ||
| 658 | .abreg = AB3100_IMRA2, | ||
| 659 | .setting = 0xFF | ||
| 660 | }, { | ||
| 661 | .abreg = AB3100_IMRA3, | ||
| 662 | .setting = 0x01 | ||
| 663 | }, { | ||
| 664 | .abreg = AB3100_IMRB1, | ||
| 665 | .setting = 0xFF | ||
| 666 | }, { | ||
| 667 | .abreg = AB3100_IMRB2, | ||
| 668 | .setting = 0xFF | ||
| 669 | }, { | ||
| 670 | .abreg = AB3100_IMRB3, | ||
| 671 | .setting = 0xFF | ||
| 672 | }, { | ||
| 673 | .abreg = AB3100_SUP, | ||
| 674 | .setting = 0x00 | ||
| 675 | }, { | ||
| 676 | .abreg = AB3100_DIS, | ||
| 677 | .setting = 0xF0 | ||
| 678 | }, { | ||
| 679 | .abreg = AB3100_D0C, | ||
| 680 | .setting = 0x00 | ||
| 681 | }, { | ||
| 682 | .abreg = AB3100_D1C, | ||
| 683 | .setting = 0x00 | ||
| 684 | }, { | ||
| 685 | .abreg = AB3100_D2C, | ||
| 686 | .setting = 0x00 | ||
| 687 | }, { | ||
| 688 | .abreg = AB3100_D3C, | ||
| 689 | .setting = 0x00 | ||
| 690 | }, | ||
| 691 | }; | ||
| 692 | |||
| 693 | static int __init ab3100_setup(struct ab3100 *ab3100) | ||
| 694 | { | ||
| 695 | int err = 0; | ||
| 696 | int i; | ||
| 697 | |||
| 698 | for (i = 0; i < ARRAY_SIZE(ab3100_init_settings); i++) { | ||
| 699 | err = ab3100_set_register(ab3100, | ||
| 700 | ab3100_init_settings[i].abreg, | ||
| 701 | ab3100_init_settings[i].setting); | ||
| 702 | if (err) | ||
| 703 | goto exit_no_setup; | ||
| 704 | } | ||
| 705 | |||
| 706 | /* | ||
| 707 | * Special trick to make the AB3100 use the 32kHz clock (RTC) | ||
| 708 | * bit 3 in test registe 0x02 is a special, undocumented test | ||
| 709 | * register bit that only exist in AB3100 P1E | ||
| 710 | */ | ||
| 711 | if (ab3100->chip_id == 0xc4) { | ||
| 712 | dev_warn(ab3100->dev, | ||
| 713 | "AB3100 P1E variant detected, " | ||
| 714 | "forcing chip to 32KHz\n"); | ||
| 715 | err = ab3100_set_test_register(ab3100, 0x02, 0x08); | ||
| 716 | } | ||
| 717 | |||
| 718 | exit_no_setup: | ||
| 719 | return err; | ||
| 720 | } | ||
| 721 | |||
| 722 | /* | ||
| 723 | * Here we define all the platform devices that appear | ||
| 724 | * as children of the AB3100. These are regular platform | ||
| 725 | * devices with the IORESOURCE_IO .start and .end set | ||
| 726 | * to correspond to the internal AB3100 register range | ||
| 727 | * mapping to the corresponding subdevice. | ||
| 728 | */ | ||
| 729 | |||
| 730 | #define AB3100_DEVICE(devname, devid) \ | ||
| 731 | static struct platform_device ab3100_##devname##_device = { \ | ||
| 732 | .name = devid, \ | ||
| 733 | .id = -1, \ | ||
| 734 | } | ||
| 735 | |||
| 736 | /* | ||
| 737 | * This lists all the subdevices and corresponding register | ||
| 738 | * ranges. | ||
| 739 | */ | ||
| 740 | AB3100_DEVICE(dac, "ab3100-dac"); | ||
| 741 | AB3100_DEVICE(leds, "ab3100-leds"); | ||
| 742 | AB3100_DEVICE(power, "ab3100-power"); | ||
| 743 | AB3100_DEVICE(regulators, "ab3100-regulators"); | ||
| 744 | AB3100_DEVICE(sim, "ab3100-sim"); | ||
| 745 | AB3100_DEVICE(uart, "ab3100-uart"); | ||
| 746 | AB3100_DEVICE(rtc, "ab3100-rtc"); | ||
| 747 | AB3100_DEVICE(charger, "ab3100-charger"); | ||
| 748 | AB3100_DEVICE(boost, "ab3100-boost"); | ||
| 749 | AB3100_DEVICE(adc, "ab3100-adc"); | ||
| 750 | AB3100_DEVICE(fuelgauge, "ab3100-fuelgauge"); | ||
| 751 | AB3100_DEVICE(vibrator, "ab3100-vibrator"); | ||
| 752 | AB3100_DEVICE(otp, "ab3100-otp"); | ||
| 753 | AB3100_DEVICE(codec, "ab3100-codec"); | ||
| 754 | |||
| 755 | static struct platform_device * | ||
| 756 | ab3100_platform_devs[] = { | ||
| 757 | &ab3100_dac_device, | ||
| 758 | &ab3100_leds_device, | ||
| 759 | &ab3100_power_device, | ||
| 760 | &ab3100_regulators_device, | ||
| 761 | &ab3100_sim_device, | ||
| 762 | &ab3100_uart_device, | ||
| 763 | &ab3100_rtc_device, | ||
| 764 | &ab3100_charger_device, | ||
| 765 | &ab3100_boost_device, | ||
| 766 | &ab3100_adc_device, | ||
| 767 | &ab3100_fuelgauge_device, | ||
| 768 | &ab3100_vibrator_device, | ||
| 769 | &ab3100_otp_device, | ||
| 770 | &ab3100_codec_device, | ||
| 771 | }; | ||
| 772 | |||
| 773 | struct ab_family_id { | ||
| 774 | u8 id; | ||
| 775 | char *name; | ||
| 776 | }; | ||
| 777 | |||
| 778 | static const struct ab_family_id ids[] __initdata = { | ||
| 779 | /* AB3100 */ | ||
| 780 | { | ||
| 781 | .id = 0xc0, | ||
| 782 | .name = "P1A" | ||
| 783 | }, { | ||
| 784 | .id = 0xc1, | ||
| 785 | .name = "P1B" | ||
| 786 | }, { | ||
| 787 | .id = 0xc2, | ||
| 788 | .name = "P1C" | ||
| 789 | }, { | ||
| 790 | .id = 0xc3, | ||
| 791 | .name = "P1D" | ||
| 792 | }, { | ||
| 793 | .id = 0xc4, | ||
| 794 | .name = "P1E" | ||
| 795 | }, { | ||
| 796 | .id = 0xc5, | ||
| 797 | .name = "P1F/R1A" | ||
| 798 | }, { | ||
| 799 | .id = 0xc6, | ||
| 800 | .name = "P1G/R1A" | ||
| 801 | }, { | ||
| 802 | .id = 0xc7, | ||
| 803 | .name = "P2A/R2A" | ||
| 804 | }, { | ||
| 805 | .id = 0xc8, | ||
| 806 | .name = "P2B/R2B" | ||
| 807 | }, | ||
| 808 | /* AB3000 variants, not supported */ | ||
| 809 | { | ||
| 810 | .id = 0xa0 | ||
| 811 | }, { | ||
| 812 | .id = 0xa1 | ||
| 813 | }, { | ||
| 814 | .id = 0xa2 | ||
| 815 | }, { | ||
| 816 | .id = 0xa3 | ||
| 817 | }, { | ||
| 818 | .id = 0xa4 | ||
| 819 | }, { | ||
| 820 | .id = 0xa5 | ||
| 821 | }, { | ||
| 822 | .id = 0xa6 | ||
| 823 | }, { | ||
| 824 | .id = 0xa7 | ||
| 825 | }, | ||
| 826 | /* Terminator */ | ||
| 827 | { | ||
| 828 | .id = 0x00, | ||
| 829 | }, | ||
| 830 | }; | ||
| 831 | |||
| 832 | static int __init ab3100_probe(struct i2c_client *client, | ||
| 833 | const struct i2c_device_id *id) | ||
| 834 | { | ||
| 835 | struct ab3100 *ab3100; | ||
| 836 | int err; | ||
| 837 | int i; | ||
| 838 | |||
| 839 | ab3100 = kzalloc(sizeof(struct ab3100), GFP_KERNEL); | ||
| 840 | if (!ab3100) { | ||
| 841 | dev_err(&client->dev, "could not allocate AB3100 device\n"); | ||
| 842 | return -ENOMEM; | ||
| 843 | } | ||
| 844 | |||
| 845 | /* Initialize data structure */ | ||
| 846 | mutex_init(&ab3100->access_mutex); | ||
| 847 | BLOCKING_INIT_NOTIFIER_HEAD(&ab3100->event_subscribers); | ||
| 848 | |||
| 849 | ab3100->i2c_client = client; | ||
| 850 | ab3100->dev = &ab3100->i2c_client->dev; | ||
| 851 | |||
| 852 | i2c_set_clientdata(client, ab3100); | ||
| 853 | |||
| 854 | /* Read chip ID register */ | ||
| 855 | err = ab3100_get_register(ab3100, AB3100_CID, | ||
| 856 | &ab3100->chip_id); | ||
| 857 | if (err) { | ||
| 858 | dev_err(&client->dev, | ||
| 859 | "could not communicate with the AB3100 analog " | ||
| 860 | "baseband chip\n"); | ||
| 861 | goto exit_no_detect; | ||
| 862 | } | ||
| 863 | |||
| 864 | for (i = 0; ids[i].id != 0x0; i++) { | ||
| 865 | if (ids[i].id == ab3100->chip_id) { | ||
| 866 | if (ids[i].name != NULL) { | ||
| 867 | snprintf(&ab3100->chip_name[0], | ||
| 868 | sizeof(ab3100->chip_name) - 1, | ||
| 869 | "AB3100 %s", | ||
| 870 | ids[i].name); | ||
| 871 | break; | ||
| 872 | } else { | ||
| 873 | dev_err(&client->dev, | ||
| 874 | "AB3000 is not supported\n"); | ||
| 875 | goto exit_no_detect; | ||
| 876 | } | ||
| 877 | } | ||
| 878 | } | ||
| 879 | |||
| 880 | if (ids[i].id == 0x0) { | ||
| 881 | dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n", | ||
| 882 | ab3100->chip_id); | ||
| 883 | dev_err(&client->dev, "accepting it anyway. Please update " | ||
| 884 | "the driver.\n"); | ||
| 885 | goto exit_no_detect; | ||
| 886 | } | ||
| 887 | |||
| 888 | dev_info(&client->dev, "Detected chip: %s\n", | ||
| 889 | &ab3100->chip_name[0]); | ||
| 890 | |||
| 891 | /* Attach a second dummy i2c_client to the test register address */ | ||
| 892 | ab3100->testreg_client = i2c_new_dummy(client->adapter, | ||
| 893 | client->addr + 1); | ||
| 894 | if (!ab3100->testreg_client) { | ||
| 895 | err = -ENOMEM; | ||
| 896 | goto exit_no_testreg_client; | ||
| 897 | } | ||
| 898 | |||
| 899 | strlcpy(ab3100->testreg_client->name, id->name, | ||
| 900 | sizeof(ab3100->testreg_client->name)); | ||
| 901 | |||
| 902 | err = ab3100_setup(ab3100); | ||
| 903 | if (err) | ||
| 904 | goto exit_no_setup; | ||
| 905 | |||
| 906 | INIT_WORK(&ab3100->work, ab3100_work); | ||
| 907 | |||
| 908 | /* This real unpredictable IRQ is of course sampled for entropy */ | ||
| 909 | err = request_irq(client->irq, ab3100_irq_handler, | ||
| 910 | IRQF_DISABLED | IRQF_SAMPLE_RANDOM, | ||
| 911 | "AB3100 IRQ", ab3100); | ||
| 912 | if (err) | ||
| 913 | goto exit_no_irq; | ||
| 914 | |||
| 915 | /* Set parent and a pointer back to the container in device data */ | ||
| 916 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { | ||
| 917 | ab3100_platform_devs[i]->dev.parent = | ||
| 918 | &client->dev; | ||
| 919 | platform_set_drvdata(ab3100_platform_devs[i], ab3100); | ||
| 920 | } | ||
| 921 | |||
| 922 | /* Register the platform devices */ | ||
| 923 | platform_add_devices(ab3100_platform_devs, | ||
| 924 | ARRAY_SIZE(ab3100_platform_devs)); | ||
| 925 | |||
| 926 | ab3100_setup_debugfs(ab3100); | ||
| 927 | |||
| 928 | return 0; | ||
| 929 | |||
| 930 | exit_no_irq: | ||
| 931 | exit_no_setup: | ||
| 932 | i2c_unregister_device(ab3100->testreg_client); | ||
| 933 | exit_no_testreg_client: | ||
| 934 | exit_no_detect: | ||
| 935 | kfree(ab3100); | ||
| 936 | return err; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int __exit ab3100_remove(struct i2c_client *client) | ||
| 940 | { | ||
| 941 | struct ab3100 *ab3100 = i2c_get_clientdata(client); | ||
| 942 | int i; | ||
| 943 | |||
| 944 | /* Unregister subdevices */ | ||
| 945 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) | ||
| 946 | platform_device_unregister(ab3100_platform_devs[i]); | ||
| 947 | |||
| 948 | ab3100_remove_debugfs(); | ||
| 949 | i2c_unregister_device(ab3100->testreg_client); | ||
| 950 | |||
| 951 | /* | ||
| 952 | * At this point, all subscribers should have unregistered | ||
| 953 | * their notifiers so deactivate IRQ | ||
| 954 | */ | ||
| 955 | free_irq(client->irq, ab3100); | ||
| 956 | kfree(ab3100); | ||
| 957 | return 0; | ||
| 958 | } | ||
| 959 | |||
| 960 | static const struct i2c_device_id ab3100_id[] = { | ||
| 961 | { "ab3100", ab3100 }, | ||
| 962 | { } | ||
| 963 | }; | ||
| 964 | MODULE_DEVICE_TABLE(i2c, ab3100_id); | ||
| 965 | |||
| 966 | static struct i2c_driver ab3100_driver = { | ||
| 967 | .driver = { | ||
| 968 | .name = "ab3100", | ||
| 969 | .owner = THIS_MODULE, | ||
| 970 | }, | ||
| 971 | .id_table = ab3100_id, | ||
| 972 | .probe = ab3100_probe, | ||
| 973 | .remove = __exit_p(ab3100_remove), | ||
| 974 | }; | ||
| 975 | |||
| 976 | static int __init ab3100_i2c_init(void) | ||
| 977 | { | ||
| 978 | return i2c_add_driver(&ab3100_driver); | ||
| 979 | } | ||
| 980 | |||
| 981 | static void __exit ab3100_i2c_exit(void) | ||
| 982 | { | ||
| 983 | i2c_del_driver(&ab3100_driver); | ||
| 984 | } | ||
| 985 | |||
| 986 | subsys_initcall(ab3100_i2c_init); | ||
| 987 | module_exit(ab3100_i2c_exit); | ||
| 988 | |||
| 989 | MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); | ||
| 990 | MODULE_DESCRIPTION("AB3100 core driver"); | ||
| 991 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index 9e485459f63b..63a2a6632106 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
| 20 | #include <linux/delay.h> | ||
| 20 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
| 21 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
| 22 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| @@ -24,6 +25,51 @@ | |||
| 24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 25 | 26 | ||
| 26 | #include <linux/mfd/asic3.h> | 27 | #include <linux/mfd/asic3.h> |
| 28 | #include <linux/mfd/core.h> | ||
| 29 | #include <linux/mfd/ds1wm.h> | ||
| 30 | #include <linux/mfd/tmio.h> | ||
| 31 | |||
| 32 | enum { | ||
| 33 | ASIC3_CLOCK_SPI, | ||
| 34 | ASIC3_CLOCK_OWM, | ||
| 35 | ASIC3_CLOCK_PWM0, | ||
| 36 | ASIC3_CLOCK_PWM1, | ||
| 37 | ASIC3_CLOCK_LED0, | ||
| 38 | ASIC3_CLOCK_LED1, | ||
| 39 | ASIC3_CLOCK_LED2, | ||
| 40 | ASIC3_CLOCK_SD_HOST, | ||
| 41 | ASIC3_CLOCK_SD_BUS, | ||
| 42 | ASIC3_CLOCK_SMBUS, | ||
| 43 | ASIC3_CLOCK_EX0, | ||
| 44 | ASIC3_CLOCK_EX1, | ||
| 45 | }; | ||
| 46 | |||
| 47 | struct asic3_clk { | ||
| 48 | int enabled; | ||
| 49 | unsigned int cdex; | ||
| 50 | unsigned long rate; | ||
| 51 | }; | ||
| 52 | |||
| 53 | #define INIT_CDEX(_name, _rate) \ | ||
| 54 | [ASIC3_CLOCK_##_name] = { \ | ||
| 55 | .cdex = CLOCK_CDEX_##_name, \ | ||
| 56 | .rate = _rate, \ | ||
| 57 | } | ||
| 58 | |||
| 59 | struct asic3_clk asic3_clk_init[] __initdata = { | ||
| 60 | INIT_CDEX(SPI, 0), | ||
| 61 | INIT_CDEX(OWM, 5000000), | ||
| 62 | INIT_CDEX(PWM0, 0), | ||
| 63 | INIT_CDEX(PWM1, 0), | ||
| 64 | INIT_CDEX(LED0, 0), | ||
| 65 | INIT_CDEX(LED1, 0), | ||
| 66 | INIT_CDEX(LED2, 0), | ||
| 67 | INIT_CDEX(SD_HOST, 24576000), | ||
| 68 | INIT_CDEX(SD_BUS, 12288000), | ||
| 69 | INIT_CDEX(SMBUS, 0), | ||
| 70 | INIT_CDEX(EX0, 32768), | ||
| 71 | INIT_CDEX(EX1, 24576000), | ||
| 72 | }; | ||
| 27 | 73 | ||
| 28 | struct asic3 { | 74 | struct asic3 { |
| 29 | void __iomem *mapping; | 75 | void __iomem *mapping; |
| @@ -34,6 +80,8 @@ struct asic3 { | |||
| 34 | u16 irq_bothedge[4]; | 80 | u16 irq_bothedge[4]; |
| 35 | struct gpio_chip gpio; | 81 | struct gpio_chip gpio; |
| 36 | struct device *dev; | 82 | struct device *dev; |
| 83 | |||
| 84 | struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)]; | ||
| 37 | }; | 85 | }; |
| 38 | 86 | ||
| 39 | static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); | 87 | static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset); |
| @@ -52,6 +100,21 @@ static inline u32 asic3_read_register(struct asic3 *asic, | |||
| 52 | (reg >> asic->bus_shift)); | 100 | (reg >> asic->bus_shift)); |
| 53 | } | 101 | } |
| 54 | 102 | ||
| 103 | void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set) | ||
| 104 | { | ||
| 105 | unsigned long flags; | ||
| 106 | u32 val; | ||
| 107 | |||
| 108 | spin_lock_irqsave(&asic->lock, flags); | ||
| 109 | val = asic3_read_register(asic, reg); | ||
| 110 | if (set) | ||
| 111 | val |= bits; | ||
| 112 | else | ||
| 113 | val &= ~bits; | ||
| 114 | asic3_write_register(asic, reg, val); | ||
| 115 | spin_unlock_irqrestore(&asic->lock, flags); | ||
| 116 | } | ||
| 117 | |||
| 55 | /* IRQs */ | 118 | /* IRQs */ |
| 56 | #define MAX_ASIC_ISR_LOOPS 20 | 119 | #define MAX_ASIC_ISR_LOOPS 20 |
| 57 | #define ASIC3_GPIO_BASE_INCR \ | 120 | #define ASIC3_GPIO_BASE_INCR \ |
| @@ -525,6 +588,240 @@ static int asic3_gpio_remove(struct platform_device *pdev) | |||
| 525 | return gpiochip_remove(&asic->gpio); | 588 | return gpiochip_remove(&asic->gpio); |
| 526 | } | 589 | } |
| 527 | 590 | ||
| 591 | static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk) | ||
| 592 | { | ||
| 593 | unsigned long flags; | ||
| 594 | u32 cdex; | ||
| 595 | |||
| 596 | spin_lock_irqsave(&asic->lock, flags); | ||
| 597 | if (clk->enabled++ == 0) { | ||
| 598 | cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX)); | ||
| 599 | cdex |= clk->cdex; | ||
| 600 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex); | ||
| 601 | } | ||
| 602 | spin_unlock_irqrestore(&asic->lock, flags); | ||
| 603 | |||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | |||
| 607 | static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk) | ||
| 608 | { | ||
| 609 | unsigned long flags; | ||
| 610 | u32 cdex; | ||
| 611 | |||
| 612 | WARN_ON(clk->enabled == 0); | ||
| 613 | |||
| 614 | spin_lock_irqsave(&asic->lock, flags); | ||
| 615 | if (--clk->enabled == 0) { | ||
| 616 | cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX)); | ||
| 617 | cdex &= ~clk->cdex; | ||
| 618 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex); | ||
| 619 | } | ||
| 620 | spin_unlock_irqrestore(&asic->lock, flags); | ||
| 621 | } | ||
| 622 | |||
| 623 | /* MFD cells (SPI, PWM, LED, DS1WM, MMC) */ | ||
| 624 | static struct ds1wm_driver_data ds1wm_pdata = { | ||
| 625 | .active_high = 1, | ||
| 626 | }; | ||
| 627 | |||
| 628 | static struct resource ds1wm_resources[] = { | ||
| 629 | { | ||
| 630 | .start = ASIC3_OWM_BASE, | ||
| 631 | .end = ASIC3_OWM_BASE + 0x13, | ||
| 632 | .flags = IORESOURCE_MEM, | ||
| 633 | }, | ||
| 634 | { | ||
| 635 | .start = ASIC3_IRQ_OWM, | ||
| 636 | .start = ASIC3_IRQ_OWM, | ||
| 637 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, | ||
| 638 | }, | ||
| 639 | }; | ||
| 640 | |||
| 641 | static int ds1wm_enable(struct platform_device *pdev) | ||
| 642 | { | ||
| 643 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
| 644 | |||
| 645 | /* Turn on external clocks and the OWM clock */ | ||
| 646 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]); | ||
| 647 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]); | ||
| 648 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_OWM]); | ||
| 649 | msleep(1); | ||
| 650 | |||
| 651 | /* Reset and enable DS1WM */ | ||
| 652 | asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET), | ||
| 653 | ASIC3_EXTCF_OWM_RESET, 1); | ||
| 654 | msleep(1); | ||
| 655 | asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET), | ||
| 656 | ASIC3_EXTCF_OWM_RESET, 0); | ||
| 657 | msleep(1); | ||
| 658 | asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT), | ||
| 659 | ASIC3_EXTCF_OWM_EN, 1); | ||
| 660 | msleep(1); | ||
| 661 | |||
| 662 | return 0; | ||
| 663 | } | ||
| 664 | |||
| 665 | static int ds1wm_disable(struct platform_device *pdev) | ||
| 666 | { | ||
| 667 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
| 668 | |||
| 669 | asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT), | ||
| 670 | ASIC3_EXTCF_OWM_EN, 0); | ||
| 671 | |||
| 672 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_OWM]); | ||
| 673 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]); | ||
| 674 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]); | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | static struct mfd_cell asic3_cell_ds1wm = { | ||
| 680 | .name = "ds1wm", | ||
| 681 | .enable = ds1wm_enable, | ||
| 682 | .disable = ds1wm_disable, | ||
| 683 | .driver_data = &ds1wm_pdata, | ||
| 684 | .num_resources = ARRAY_SIZE(ds1wm_resources), | ||
| 685 | .resources = ds1wm_resources, | ||
| 686 | }; | ||
| 687 | |||
| 688 | static struct tmio_mmc_data asic3_mmc_data = { | ||
| 689 | .hclk = 24576000, | ||
| 690 | }; | ||
| 691 | |||
| 692 | static struct resource asic3_mmc_resources[] = { | ||
| 693 | { | ||
| 694 | .start = ASIC3_SD_CTRL_BASE, | ||
| 695 | .end = ASIC3_SD_CTRL_BASE + 0x3ff, | ||
| 696 | .flags = IORESOURCE_MEM, | ||
| 697 | }, | ||
| 698 | { | ||
| 699 | .start = ASIC3_SD_CONFIG_BASE, | ||
| 700 | .end = ASIC3_SD_CONFIG_BASE + 0x1ff, | ||
| 701 | .flags = IORESOURCE_MEM, | ||
| 702 | }, | ||
| 703 | { | ||
| 704 | .start = 0, | ||
| 705 | .end = 0, | ||
| 706 | .flags = IORESOURCE_IRQ, | ||
| 707 | }, | ||
| 708 | }; | ||
| 709 | |||
| 710 | static int asic3_mmc_enable(struct platform_device *pdev) | ||
| 711 | { | ||
| 712 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
| 713 | |||
| 714 | /* Not sure if it must be done bit by bit, but leaving as-is */ | ||
| 715 | asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), | ||
| 716 | ASIC3_SDHWCTRL_LEVCD, 1); | ||
| 717 | asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), | ||
| 718 | ASIC3_SDHWCTRL_LEVWP, 1); | ||
| 719 | asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), | ||
| 720 | ASIC3_SDHWCTRL_SUSPEND, 0); | ||
| 721 | asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), | ||
| 722 | ASIC3_SDHWCTRL_PCLR, 0); | ||
| 723 | |||
| 724 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]); | ||
| 725 | /* CLK32 used for card detection and for interruption detection | ||
| 726 | * when HCLK is stopped. | ||
| 727 | */ | ||
| 728 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]); | ||
| 729 | msleep(1); | ||
| 730 | |||
| 731 | /* HCLK 24.576 MHz, BCLK 12.288 MHz: */ | ||
| 732 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), | ||
| 733 | CLOCK_SEL_CX | CLOCK_SEL_SD_HCLK_SEL); | ||
| 734 | |||
| 735 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]); | ||
| 736 | asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]); | ||
| 737 | msleep(1); | ||
| 738 | |||
| 739 | asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT), | ||
| 740 | ASIC3_EXTCF_SD_MEM_ENABLE, 1); | ||
| 741 | |||
| 742 | /* Enable SD card slot 3.3V power supply */ | ||
| 743 | asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), | ||
| 744 | ASIC3_SDHWCTRL_SDPWR, 1); | ||
| 745 | |||
| 746 | return 0; | ||
| 747 | } | ||
| 748 | |||
| 749 | static int asic3_mmc_disable(struct platform_device *pdev) | ||
| 750 | { | ||
| 751 | struct asic3 *asic = dev_get_drvdata(pdev->dev.parent); | ||
| 752 | |||
| 753 | /* Put in suspend mode */ | ||
| 754 | asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), | ||
| 755 | ASIC3_SDHWCTRL_SUSPEND, 1); | ||
| 756 | |||
| 757 | /* Disable clocks */ | ||
| 758 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]); | ||
| 759 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]); | ||
| 760 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]); | ||
| 761 | asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]); | ||
| 762 | return 0; | ||
| 763 | } | ||
| 764 | |||
| 765 | static struct mfd_cell asic3_cell_mmc = { | ||
| 766 | .name = "tmio-mmc", | ||
| 767 | .enable = asic3_mmc_enable, | ||
| 768 | .disable = asic3_mmc_disable, | ||
| 769 | .driver_data = &asic3_mmc_data, | ||
| 770 | .num_resources = ARRAY_SIZE(asic3_mmc_resources), | ||
| 771 | .resources = asic3_mmc_resources, | ||
| 772 | }; | ||
| 773 | |||
| 774 | static int __init asic3_mfd_probe(struct platform_device *pdev, | ||
| 775 | struct resource *mem) | ||
| 776 | { | ||
| 777 | struct asic3 *asic = platform_get_drvdata(pdev); | ||
| 778 | struct resource *mem_sdio; | ||
| 779 | int irq, ret; | ||
| 780 | |||
| 781 | mem_sdio = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 782 | if (!mem_sdio) | ||
| 783 | dev_dbg(asic->dev, "no SDIO MEM resource\n"); | ||
| 784 | |||
| 785 | irq = platform_get_irq(pdev, 1); | ||
| 786 | if (irq < 0) | ||
| 787 | dev_dbg(asic->dev, "no SDIO IRQ resource\n"); | ||
| 788 | |||
| 789 | /* DS1WM */ | ||
| 790 | asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT), | ||
| 791 | ASIC3_EXTCF_OWM_SMB, 0); | ||
| 792 | |||
| 793 | ds1wm_resources[0].start >>= asic->bus_shift; | ||
| 794 | ds1wm_resources[0].end >>= asic->bus_shift; | ||
| 795 | |||
| 796 | asic3_cell_ds1wm.platform_data = &asic3_cell_ds1wm; | ||
| 797 | asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm); | ||
| 798 | |||
| 799 | /* MMC */ | ||
| 800 | asic3_mmc_resources[0].start >>= asic->bus_shift; | ||
| 801 | asic3_mmc_resources[0].end >>= asic->bus_shift; | ||
| 802 | asic3_mmc_resources[1].start >>= asic->bus_shift; | ||
| 803 | asic3_mmc_resources[1].end >>= asic->bus_shift; | ||
| 804 | |||
| 805 | asic3_cell_mmc.platform_data = &asic3_cell_mmc; | ||
| 806 | asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc); | ||
| 807 | |||
| 808 | ret = mfd_add_devices(&pdev->dev, pdev->id, | ||
| 809 | &asic3_cell_ds1wm, 1, mem, asic->irq_base); | ||
| 810 | if (ret < 0) | ||
| 811 | goto out; | ||
| 812 | |||
| 813 | if (mem_sdio && (irq >= 0)) | ||
| 814 | ret = mfd_add_devices(&pdev->dev, pdev->id, | ||
| 815 | &asic3_cell_mmc, 1, mem_sdio, irq); | ||
| 816 | |||
| 817 | out: | ||
| 818 | return ret; | ||
| 819 | } | ||
| 820 | |||
| 821 | static void asic3_mfd_remove(struct platform_device *pdev) | ||
| 822 | { | ||
| 823 | mfd_remove_devices(&pdev->dev); | ||
| 824 | } | ||
| 528 | 825 | ||
| 529 | /* Core */ | 826 | /* Core */ |
| 530 | static int __init asic3_probe(struct platform_device *pdev) | 827 | static int __init asic3_probe(struct platform_device *pdev) |
| @@ -533,7 +830,6 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
| 533 | struct asic3 *asic; | 830 | struct asic3 *asic; |
| 534 | struct resource *mem; | 831 | struct resource *mem; |
| 535 | unsigned long clksel; | 832 | unsigned long clksel; |
| 536 | int map_size; | ||
| 537 | int ret = 0; | 833 | int ret = 0; |
| 538 | 834 | ||
| 539 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); | 835 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); |
| @@ -553,8 +849,7 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
| 553 | goto out_free; | 849 | goto out_free; |
| 554 | } | 850 | } |
| 555 | 851 | ||
| 556 | map_size = mem->end - mem->start + 1; | 852 | asic->mapping = ioremap(mem->start, resource_size(mem)); |
| 557 | asic->mapping = ioremap(mem->start, map_size); | ||
| 558 | if (!asic->mapping) { | 853 | if (!asic->mapping) { |
| 559 | ret = -ENOMEM; | 854 | ret = -ENOMEM; |
| 560 | dev_err(asic->dev, "Couldn't ioremap\n"); | 855 | dev_err(asic->dev, "Couldn't ioremap\n"); |
| @@ -564,7 +859,7 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
| 564 | asic->irq_base = pdata->irq_base; | 859 | asic->irq_base = pdata->irq_base; |
| 565 | 860 | ||
| 566 | /* calculate bus shift from mem resource */ | 861 | /* calculate bus shift from mem resource */ |
| 567 | asic->bus_shift = 2 - (map_size >> 12); | 862 | asic->bus_shift = 2 - (resource_size(mem) >> 12); |
| 568 | 863 | ||
| 569 | clksel = 0; | 864 | clksel = 0; |
| 570 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); | 865 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); |
| @@ -590,6 +885,13 @@ static int __init asic3_probe(struct platform_device *pdev) | |||
| 590 | goto out_irq; | 885 | goto out_irq; |
| 591 | } | 886 | } |
| 592 | 887 | ||
| 888 | /* Making a per-device copy is only needed for the | ||
| 889 | * theoretical case of multiple ASIC3s on one board: | ||
| 890 | */ | ||
| 891 | memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init)); | ||
| 892 | |||
| 893 | asic3_mfd_probe(pdev, mem); | ||
| 894 | |||
| 593 | dev_info(asic->dev, "ASIC3 Core driver\n"); | 895 | dev_info(asic->dev, "ASIC3 Core driver\n"); |
| 594 | 896 | ||
| 595 | return 0; | 897 | return 0; |
| @@ -611,6 +913,8 @@ static int asic3_remove(struct platform_device *pdev) | |||
| 611 | int ret; | 913 | int ret; |
| 612 | struct asic3 *asic = platform_get_drvdata(pdev); | 914 | struct asic3 *asic = platform_get_drvdata(pdev); |
| 613 | 915 | ||
| 916 | asic3_mfd_remove(pdev); | ||
| 917 | |||
| 614 | ret = asic3_gpio_remove(pdev); | 918 | ret = asic3_gpio_remove(pdev); |
| 615 | if (ret < 0) | 919 | if (ret < 0) |
| 616 | return ret; | 920 | return ret; |
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 7283d88656af..e5ffe5617393 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
| @@ -561,7 +561,7 @@ static int __init da903x_init(void) | |||
| 561 | { | 561 | { |
| 562 | return i2c_add_driver(&da903x_driver); | 562 | return i2c_add_driver(&da903x_driver); |
| 563 | } | 563 | } |
| 564 | module_init(da903x_init); | 564 | subsys_initcall(da903x_init); |
| 565 | 565 | ||
| 566 | static void __exit da903x_exit(void) | 566 | static void __exit da903x_exit(void) |
| 567 | { | 567 | { |
diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c new file mode 100644 index 000000000000..671a7efe86a8 --- /dev/null +++ b/drivers/mfd/ezx-pcap.c | |||
| @@ -0,0 +1,505 @@ | |||
| 1 | /* | ||
| 2 | * Driver for Motorola PCAP2 as present in EZX phones | ||
| 3 | * | ||
| 4 | * Copyright (C) 2006 Harald Welte <laforge@openezx.org> | ||
| 5 | * Copyright (C) 2009 Daniel Ribeiro <drwyrm@gmail.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | * | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/interrupt.h> | ||
| 17 | #include <linux/irq.h> | ||
| 18 | #include <linux/mfd/ezx-pcap.h> | ||
| 19 | #include <linux/spi/spi.h> | ||
| 20 | |||
| 21 | #define PCAP_ADC_MAXQ 8 | ||
| 22 | struct pcap_adc_request { | ||
| 23 | u8 bank; | ||
| 24 | u8 ch[2]; | ||
| 25 | u32 flags; | ||
| 26 | void (*callback)(void *, u16[]); | ||
| 27 | void *data; | ||
| 28 | }; | ||
| 29 | |||
| 30 | struct pcap_adc_sync_request { | ||
| 31 | u16 res[2]; | ||
| 32 | struct completion completion; | ||
| 33 | }; | ||
| 34 | |||
| 35 | struct pcap_chip { | ||
| 36 | struct spi_device *spi; | ||
| 37 | |||
| 38 | /* IO */ | ||
| 39 | u32 buf; | ||
| 40 | struct mutex io_mutex; | ||
| 41 | |||
| 42 | /* IRQ */ | ||
| 43 | unsigned int irq_base; | ||
| 44 | u32 msr; | ||
| 45 | struct work_struct isr_work; | ||
| 46 | struct work_struct msr_work; | ||
| 47 | struct workqueue_struct *workqueue; | ||
| 48 | |||
| 49 | /* ADC */ | ||
| 50 | struct pcap_adc_request *adc_queue[PCAP_ADC_MAXQ]; | ||
| 51 | u8 adc_head; | ||
| 52 | u8 adc_tail; | ||
| 53 | struct mutex adc_mutex; | ||
| 54 | }; | ||
| 55 | |||
| 56 | /* IO */ | ||
| 57 | static int ezx_pcap_putget(struct pcap_chip *pcap, u32 *data) | ||
| 58 | { | ||
| 59 | struct spi_transfer t; | ||
| 60 | struct spi_message m; | ||
| 61 | int status; | ||
| 62 | |||
| 63 | memset(&t, 0, sizeof t); | ||
| 64 | spi_message_init(&m); | ||
| 65 | t.len = sizeof(u32); | ||
| 66 | spi_message_add_tail(&t, &m); | ||
| 67 | |||
| 68 | pcap->buf = *data; | ||
| 69 | t.tx_buf = (u8 *) &pcap->buf; | ||
| 70 | t.rx_buf = (u8 *) &pcap->buf; | ||
| 71 | status = spi_sync(pcap->spi, &m); | ||
| 72 | |||
| 73 | if (status == 0) | ||
| 74 | *data = pcap->buf; | ||
| 75 | |||
| 76 | return status; | ||
| 77 | } | ||
| 78 | |||
| 79 | int ezx_pcap_write(struct pcap_chip *pcap, u8 reg_num, u32 value) | ||
| 80 | { | ||
| 81 | int ret; | ||
| 82 | |||
| 83 | mutex_lock(&pcap->io_mutex); | ||
| 84 | value &= PCAP_REGISTER_VALUE_MASK; | ||
| 85 | value |= PCAP_REGISTER_WRITE_OP_BIT | ||
| 86 | | (reg_num << PCAP_REGISTER_ADDRESS_SHIFT); | ||
| 87 | ret = ezx_pcap_putget(pcap, &value); | ||
| 88 | mutex_unlock(&pcap->io_mutex); | ||
| 89 | |||
| 90 | return ret; | ||
| 91 | } | ||
| 92 | EXPORT_SYMBOL_GPL(ezx_pcap_write); | ||
| 93 | |||
| 94 | int ezx_pcap_read(struct pcap_chip *pcap, u8 reg_num, u32 *value) | ||
| 95 | { | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | mutex_lock(&pcap->io_mutex); | ||
| 99 | *value = PCAP_REGISTER_READ_OP_BIT | ||
| 100 | | (reg_num << PCAP_REGISTER_ADDRESS_SHIFT); | ||
| 101 | |||
| 102 | ret = ezx_pcap_putget(pcap, value); | ||
| 103 | mutex_unlock(&pcap->io_mutex); | ||
| 104 | |||
| 105 | return ret; | ||
| 106 | } | ||
| 107 | EXPORT_SYMBOL_GPL(ezx_pcap_read); | ||
| 108 | |||
| 109 | /* IRQ */ | ||
| 110 | static inline unsigned int irq2pcap(struct pcap_chip *pcap, int irq) | ||
| 111 | { | ||
| 112 | return 1 << (irq - pcap->irq_base); | ||
| 113 | } | ||
| 114 | |||
| 115 | int pcap_to_irq(struct pcap_chip *pcap, int irq) | ||
| 116 | { | ||
| 117 | return pcap->irq_base + irq; | ||
| 118 | } | ||
| 119 | EXPORT_SYMBOL_GPL(pcap_to_irq); | ||
| 120 | |||
| 121 | static void pcap_mask_irq(unsigned int irq) | ||
| 122 | { | ||
| 123 | struct pcap_chip *pcap = get_irq_chip_data(irq); | ||
| 124 | |||
| 125 | pcap->msr |= irq2pcap(pcap, irq); | ||
| 126 | queue_work(pcap->workqueue, &pcap->msr_work); | ||
| 127 | } | ||
| 128 | |||
| 129 | static void pcap_unmask_irq(unsigned int irq) | ||
| 130 | { | ||
| 131 | struct pcap_chip *pcap = get_irq_chip_data(irq); | ||
| 132 | |||
| 133 | pcap->msr &= ~irq2pcap(pcap, irq); | ||
| 134 | queue_work(pcap->workqueue, &pcap->msr_work); | ||
| 135 | } | ||
| 136 | |||
| 137 | static struct irq_chip pcap_irq_chip = { | ||
| 138 | .name = "pcap", | ||
| 139 | .mask = pcap_mask_irq, | ||
| 140 | .unmask = pcap_unmask_irq, | ||
| 141 | }; | ||
| 142 | |||
| 143 | static void pcap_msr_work(struct work_struct *work) | ||
| 144 | { | ||
| 145 | struct pcap_chip *pcap = container_of(work, struct pcap_chip, msr_work); | ||
| 146 | |||
| 147 | ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); | ||
| 148 | } | ||
| 149 | |||
| 150 | static void pcap_isr_work(struct work_struct *work) | ||
| 151 | { | ||
| 152 | struct pcap_chip *pcap = container_of(work, struct pcap_chip, isr_work); | ||
| 153 | struct pcap_platform_data *pdata = pcap->spi->dev.platform_data; | ||
| 154 | u32 msr, isr, int_sel, service; | ||
| 155 | int irq; | ||
| 156 | |||
| 157 | ezx_pcap_read(pcap, PCAP_REG_MSR, &msr); | ||
| 158 | ezx_pcap_read(pcap, PCAP_REG_ISR, &isr); | ||
| 159 | |||
| 160 | /* We cant service/ack irqs that are assigned to port 2 */ | ||
| 161 | if (!(pdata->config & PCAP_SECOND_PORT)) { | ||
| 162 | ezx_pcap_read(pcap, PCAP_REG_INT_SEL, &int_sel); | ||
| 163 | isr &= ~int_sel; | ||
| 164 | } | ||
| 165 | ezx_pcap_write(pcap, PCAP_REG_ISR, isr); | ||
| 166 | |||
| 167 | local_irq_disable(); | ||
| 168 | service = isr & ~msr; | ||
| 169 | |||
| 170 | for (irq = pcap->irq_base; service; service >>= 1, irq++) { | ||
| 171 | if (service & 1) { | ||
| 172 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 173 | |||
| 174 | if (WARN(!desc, KERN_WARNING | ||
| 175 | "Invalid PCAP IRQ %d\n", irq)) | ||
| 176 | break; | ||
| 177 | |||
| 178 | if (desc->status & IRQ_DISABLED) | ||
| 179 | note_interrupt(irq, desc, IRQ_NONE); | ||
| 180 | else | ||
| 181 | desc->handle_irq(irq, desc); | ||
| 182 | } | ||
| 183 | } | ||
| 184 | local_irq_enable(); | ||
| 185 | } | ||
| 186 | |||
| 187 | static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
| 188 | { | ||
| 189 | struct pcap_chip *pcap = get_irq_data(irq); | ||
| 190 | |||
| 191 | desc->chip->ack(irq); | ||
| 192 | queue_work(pcap->workqueue, &pcap->isr_work); | ||
| 193 | return; | ||
| 194 | } | ||
| 195 | |||
| 196 | /* ADC */ | ||
| 197 | static void pcap_disable_adc(struct pcap_chip *pcap) | ||
| 198 | { | ||
| 199 | u32 tmp; | ||
| 200 | |||
| 201 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); | ||
| 202 | tmp &= ~(PCAP_ADC_ADEN|PCAP_ADC_BATT_I_ADC|PCAP_ADC_BATT_I_POLARITY); | ||
| 203 | ezx_pcap_write(pcap, PCAP_REG_ADC, tmp); | ||
| 204 | } | ||
| 205 | |||
| 206 | static void pcap_adc_trigger(struct pcap_chip *pcap) | ||
| 207 | { | ||
| 208 | u32 tmp; | ||
| 209 | u8 head; | ||
| 210 | |||
| 211 | mutex_lock(&pcap->adc_mutex); | ||
| 212 | head = pcap->adc_head; | ||
| 213 | if (!pcap->adc_queue[head]) { | ||
| 214 | /* queue is empty, save power */ | ||
| 215 | pcap_disable_adc(pcap); | ||
| 216 | mutex_unlock(&pcap->adc_mutex); | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | mutex_unlock(&pcap->adc_mutex); | ||
| 220 | |||
| 221 | /* start conversion on requested bank */ | ||
| 222 | tmp = pcap->adc_queue[head]->flags | PCAP_ADC_ADEN; | ||
| 223 | |||
| 224 | if (pcap->adc_queue[head]->bank == PCAP_ADC_BANK_1) | ||
| 225 | tmp |= PCAP_ADC_AD_SEL1; | ||
| 226 | |||
| 227 | ezx_pcap_write(pcap, PCAP_REG_ADC, tmp); | ||
| 228 | ezx_pcap_write(pcap, PCAP_REG_ADR, PCAP_ADR_ASC); | ||
| 229 | } | ||
| 230 | |||
| 231 | static irqreturn_t pcap_adc_irq(int irq, void *_pcap) | ||
| 232 | { | ||
| 233 | struct pcap_chip *pcap = _pcap; | ||
| 234 | struct pcap_adc_request *req; | ||
| 235 | u16 res[2]; | ||
| 236 | u32 tmp; | ||
| 237 | |||
| 238 | mutex_lock(&pcap->adc_mutex); | ||
| 239 | req = pcap->adc_queue[pcap->adc_head]; | ||
| 240 | |||
| 241 | if (WARN(!req, KERN_WARNING "adc irq without pending request\n")) | ||
| 242 | return IRQ_HANDLED; | ||
| 243 | |||
| 244 | /* read requested channels results */ | ||
| 245 | ezx_pcap_read(pcap, PCAP_REG_ADC, &tmp); | ||
| 246 | tmp &= ~(PCAP_ADC_ADA1_MASK | PCAP_ADC_ADA2_MASK); | ||
| 247 | tmp |= (req->ch[0] << PCAP_ADC_ADA1_SHIFT); | ||
| 248 | tmp |= (req->ch[1] << PCAP_ADC_ADA2_SHIFT); | ||
| 249 | ezx_pcap_write(pcap, PCAP_REG_ADC, tmp); | ||
| 250 | ezx_pcap_read(pcap, PCAP_REG_ADR, &tmp); | ||
| 251 | res[0] = (tmp & PCAP_ADR_ADD1_MASK) >> PCAP_ADR_ADD1_SHIFT; | ||
| 252 | res[1] = (tmp & PCAP_ADR_ADD2_MASK) >> PCAP_ADR_ADD2_SHIFT; | ||
| 253 | |||
| 254 | pcap->adc_queue[pcap->adc_head] = NULL; | ||
| 255 | pcap->adc_head = (pcap->adc_head + 1) & (PCAP_ADC_MAXQ - 1); | ||
| 256 | mutex_unlock(&pcap->adc_mutex); | ||
| 257 | |||
| 258 | /* pass the results and release memory */ | ||
| 259 | req->callback(req->data, res); | ||
| 260 | kfree(req); | ||
| 261 | |||
| 262 | /* trigger next conversion (if any) on queue */ | ||
| 263 | pcap_adc_trigger(pcap); | ||
| 264 | |||
| 265 | return IRQ_HANDLED; | ||
| 266 | } | ||
| 267 | |||
| 268 | int pcap_adc_async(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[], | ||
| 269 | void *callback, void *data) | ||
| 270 | { | ||
| 271 | struct pcap_adc_request *req; | ||
| 272 | |||
| 273 | /* This will be freed after we have a result */ | ||
| 274 | req = kmalloc(sizeof(struct pcap_adc_request), GFP_KERNEL); | ||
| 275 | if (!req) | ||
| 276 | return -ENOMEM; | ||
| 277 | |||
| 278 | req->bank = bank; | ||
| 279 | req->flags = flags; | ||
| 280 | req->ch[0] = ch[0]; | ||
| 281 | req->ch[1] = ch[1]; | ||
| 282 | req->callback = callback; | ||
| 283 | req->data = data; | ||
| 284 | |||
| 285 | mutex_lock(&pcap->adc_mutex); | ||
| 286 | if (pcap->adc_queue[pcap->adc_tail]) { | ||
| 287 | mutex_unlock(&pcap->adc_mutex); | ||
| 288 | kfree(req); | ||
| 289 | return -EBUSY; | ||
| 290 | } | ||
| 291 | pcap->adc_queue[pcap->adc_tail] = req; | ||
| 292 | pcap->adc_tail = (pcap->adc_tail + 1) & (PCAP_ADC_MAXQ - 1); | ||
| 293 | mutex_unlock(&pcap->adc_mutex); | ||
| 294 | |||
| 295 | /* start conversion */ | ||
| 296 | pcap_adc_trigger(pcap); | ||
| 297 | |||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | EXPORT_SYMBOL_GPL(pcap_adc_async); | ||
| 301 | |||
| 302 | static void pcap_adc_sync_cb(void *param, u16 res[]) | ||
| 303 | { | ||
| 304 | struct pcap_adc_sync_request *req = param; | ||
| 305 | |||
| 306 | req->res[0] = res[0]; | ||
| 307 | req->res[1] = res[1]; | ||
| 308 | complete(&req->completion); | ||
| 309 | } | ||
| 310 | |||
| 311 | int pcap_adc_sync(struct pcap_chip *pcap, u8 bank, u32 flags, u8 ch[], | ||
| 312 | u16 res[]) | ||
| 313 | { | ||
| 314 | struct pcap_adc_sync_request sync_data; | ||
| 315 | int ret; | ||
| 316 | |||
| 317 | init_completion(&sync_data.completion); | ||
| 318 | ret = pcap_adc_async(pcap, bank, flags, ch, pcap_adc_sync_cb, | ||
| 319 | &sync_data); | ||
| 320 | if (ret) | ||
| 321 | return ret; | ||
| 322 | wait_for_completion(&sync_data.completion); | ||
| 323 | res[0] = sync_data.res[0]; | ||
| 324 | res[1] = sync_data.res[1]; | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | EXPORT_SYMBOL_GPL(pcap_adc_sync); | ||
| 329 | |||
| 330 | /* subdevs */ | ||
| 331 | static int pcap_remove_subdev(struct device *dev, void *unused) | ||
| 332 | { | ||
| 333 | platform_device_unregister(to_platform_device(dev)); | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int __devinit pcap_add_subdev(struct pcap_chip *pcap, | ||
| 338 | struct pcap_subdev *subdev) | ||
| 339 | { | ||
| 340 | struct platform_device *pdev; | ||
| 341 | |||
| 342 | pdev = platform_device_alloc(subdev->name, subdev->id); | ||
| 343 | pdev->dev.parent = &pcap->spi->dev; | ||
| 344 | pdev->dev.platform_data = subdev->platform_data; | ||
| 345 | platform_set_drvdata(pdev, pcap); | ||
| 346 | |||
| 347 | return platform_device_add(pdev); | ||
| 348 | } | ||
| 349 | |||
| 350 | static int __devexit ezx_pcap_remove(struct spi_device *spi) | ||
| 351 | { | ||
| 352 | struct pcap_chip *pcap = dev_get_drvdata(&spi->dev); | ||
| 353 | struct pcap_platform_data *pdata = spi->dev.platform_data; | ||
| 354 | int i, adc_irq; | ||
| 355 | |||
| 356 | /* remove all registered subdevs */ | ||
| 357 | device_for_each_child(&spi->dev, NULL, pcap_remove_subdev); | ||
| 358 | |||
| 359 | /* cleanup ADC */ | ||
| 360 | adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ? | ||
| 361 | PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE); | ||
| 362 | free_irq(adc_irq, pcap); | ||
| 363 | mutex_lock(&pcap->adc_mutex); | ||
| 364 | for (i = 0; i < PCAP_ADC_MAXQ; i++) | ||
| 365 | kfree(pcap->adc_queue[i]); | ||
| 366 | mutex_unlock(&pcap->adc_mutex); | ||
| 367 | |||
| 368 | /* cleanup irqchip */ | ||
| 369 | for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) | ||
| 370 | set_irq_chip_and_handler(i, NULL, NULL); | ||
| 371 | |||
| 372 | destroy_workqueue(pcap->workqueue); | ||
| 373 | |||
| 374 | kfree(pcap); | ||
| 375 | |||
| 376 | return 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | static int __devinit ezx_pcap_probe(struct spi_device *spi) | ||
| 380 | { | ||
| 381 | struct pcap_platform_data *pdata = spi->dev.platform_data; | ||
| 382 | struct pcap_chip *pcap; | ||
| 383 | int i, adc_irq; | ||
| 384 | int ret = -ENODEV; | ||
| 385 | |||
| 386 | /* platform data is required */ | ||
| 387 | if (!pdata) | ||
| 388 | goto ret; | ||
| 389 | |||
| 390 | pcap = kzalloc(sizeof(*pcap), GFP_KERNEL); | ||
| 391 | if (!pcap) { | ||
| 392 | ret = -ENOMEM; | ||
| 393 | goto ret; | ||
| 394 | } | ||
| 395 | |||
| 396 | mutex_init(&pcap->io_mutex); | ||
| 397 | mutex_init(&pcap->adc_mutex); | ||
| 398 | INIT_WORK(&pcap->isr_work, pcap_isr_work); | ||
| 399 | INIT_WORK(&pcap->msr_work, pcap_msr_work); | ||
| 400 | dev_set_drvdata(&spi->dev, pcap); | ||
| 401 | |||
| 402 | /* setup spi */ | ||
| 403 | spi->bits_per_word = 32; | ||
| 404 | spi->mode = SPI_MODE_0 | (pdata->config & PCAP_CS_AH ? SPI_CS_HIGH : 0); | ||
| 405 | ret = spi_setup(spi); | ||
| 406 | if (ret) | ||
| 407 | goto free_pcap; | ||
| 408 | |||
| 409 | pcap->spi = spi; | ||
| 410 | |||
| 411 | /* setup irq */ | ||
| 412 | pcap->irq_base = pdata->irq_base; | ||
| 413 | pcap->workqueue = create_singlethread_workqueue("pcapd"); | ||
| 414 | if (!pcap->workqueue) { | ||
| 415 | dev_err(&spi->dev, "cant create pcap thread\n"); | ||
| 416 | goto free_pcap; | ||
| 417 | } | ||
| 418 | |||
| 419 | /* redirect interrupts to AP, except adcdone2 */ | ||
| 420 | if (!(pdata->config & PCAP_SECOND_PORT)) | ||
| 421 | ezx_pcap_write(pcap, PCAP_REG_INT_SEL, | ||
| 422 | (1 << PCAP_IRQ_ADCDONE2)); | ||
| 423 | |||
| 424 | /* setup irq chip */ | ||
| 425 | for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) { | ||
| 426 | set_irq_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq); | ||
| 427 | set_irq_chip_data(i, pcap); | ||
| 428 | #ifdef CONFIG_ARM | ||
| 429 | set_irq_flags(i, IRQF_VALID); | ||
| 430 | #else | ||
| 431 | set_irq_noprobe(i); | ||
| 432 | #endif | ||
| 433 | } | ||
| 434 | |||
| 435 | /* mask/ack all PCAP interrupts */ | ||
| 436 | ezx_pcap_write(pcap, PCAP_REG_MSR, PCAP_MASK_ALL_INTERRUPT); | ||
| 437 | ezx_pcap_write(pcap, PCAP_REG_ISR, PCAP_CLEAR_INTERRUPT_REGISTER); | ||
| 438 | pcap->msr = PCAP_MASK_ALL_INTERRUPT; | ||
| 439 | |||
| 440 | set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING); | ||
| 441 | set_irq_data(spi->irq, pcap); | ||
| 442 | set_irq_chained_handler(spi->irq, pcap_irq_handler); | ||
| 443 | set_irq_wake(spi->irq, 1); | ||
| 444 | |||
| 445 | /* ADC */ | ||
| 446 | adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ? | ||
| 447 | PCAP_IRQ_ADCDONE2 : PCAP_IRQ_ADCDONE); | ||
| 448 | |||
| 449 | ret = request_irq(adc_irq, pcap_adc_irq, 0, "ADC", pcap); | ||
| 450 | if (ret) | ||
| 451 | goto free_irqchip; | ||
| 452 | |||
| 453 | /* setup subdevs */ | ||
| 454 | for (i = 0; i < pdata->num_subdevs; i++) { | ||
| 455 | ret = pcap_add_subdev(pcap, &pdata->subdevs[i]); | ||
| 456 | if (ret) | ||
| 457 | goto remove_subdevs; | ||
| 458 | } | ||
| 459 | |||
| 460 | /* board specific quirks */ | ||
| 461 | if (pdata->init) | ||
| 462 | pdata->init(pcap); | ||
| 463 | |||
| 464 | return 0; | ||
| 465 | |||
| 466 | remove_subdevs: | ||
| 467 | device_for_each_child(&spi->dev, NULL, pcap_remove_subdev); | ||
| 468 | /* free_adc: */ | ||
| 469 | free_irq(adc_irq, pcap); | ||
| 470 | free_irqchip: | ||
| 471 | for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++) | ||
| 472 | set_irq_chip_and_handler(i, NULL, NULL); | ||
| 473 | /* destroy_workqueue: */ | ||
| 474 | destroy_workqueue(pcap->workqueue); | ||
| 475 | free_pcap: | ||
| 476 | kfree(pcap); | ||
| 477 | ret: | ||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | |||
| 481 | static struct spi_driver ezxpcap_driver = { | ||
| 482 | .probe = ezx_pcap_probe, | ||
| 483 | .remove = __devexit_p(ezx_pcap_remove), | ||
| 484 | .driver = { | ||
| 485 | .name = "ezx-pcap", | ||
| 486 | .owner = THIS_MODULE, | ||
| 487 | }, | ||
| 488 | }; | ||
| 489 | |||
| 490 | static int __init ezx_pcap_init(void) | ||
| 491 | { | ||
| 492 | return spi_register_driver(&ezxpcap_driver); | ||
| 493 | } | ||
| 494 | |||
| 495 | static void __exit ezx_pcap_exit(void) | ||
| 496 | { | ||
| 497 | spi_unregister_driver(&ezxpcap_driver); | ||
| 498 | } | ||
| 499 | |||
| 500 | module_init(ezx_pcap_init); | ||
| 501 | module_exit(ezx_pcap_exit); | ||
| 502 | |||
| 503 | MODULE_LICENSE("GPL"); | ||
| 504 | MODULE_AUTHOR("Daniel Ribeiro / Harald Welte"); | ||
| 505 | MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver"); | ||
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 082c197ab9b8..8d3c38bf9714 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
| @@ -705,5 +705,5 @@ MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 PMU"); | |||
| 705 | MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); | 705 | MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); |
| 706 | MODULE_LICENSE("GPL"); | 706 | MODULE_LICENSE("GPL"); |
| 707 | 707 | ||
| 708 | module_init(pcf50633_init); | 708 | subsys_initcall(pcf50633_init); |
| 709 | module_exit(pcf50633_exit); | 709 | module_exit(pcf50633_exit); |
diff --git a/drivers/mfd/pcf50633-gpio.c b/drivers/mfd/pcf50633-gpio.c index 2fa2eca5c9cc..9ab19a8f669d 100644 --- a/drivers/mfd/pcf50633-gpio.c +++ b/drivers/mfd/pcf50633-gpio.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
| 18 | #include <linux/module.h> | ||
| 18 | 19 | ||
| 19 | #include <linux/mfd/pcf50633/core.h> | 20 | #include <linux/mfd/pcf50633/core.h> |
| 20 | #include <linux/mfd/pcf50633/gpio.h> | 21 | #include <linux/mfd/pcf50633/gpio.h> |
| @@ -116,3 +117,5 @@ int pcf50633_gpio_power_supply_set(struct pcf50633 *pcf, | |||
| 116 | return pcf50633_reg_set_bit_mask(pcf, reg, mask, val); | 117 | return pcf50633_reg_set_bit_mask(pcf, reg, mask, val); |
| 117 | } | 118 | } |
| 118 | EXPORT_SYMBOL_GPL(pcf50633_gpio_power_supply_set); | 119 | EXPORT_SYMBOL_GPL(pcf50633_gpio_power_supply_set); |
| 120 | |||
| 121 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index 875f7a875734..0a255c1f1ce7 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
| @@ -108,7 +108,7 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc) | |||
| 108 | 108 | ||
| 109 | /*--------------------------------------------------------------------------*/ | 109 | /*--------------------------------------------------------------------------*/ |
| 110 | 110 | ||
| 111 | static const struct tmio_mmc_data t7166xb_mmc_data = { | 111 | static struct tmio_mmc_data t7166xb_mmc_data = { |
| 112 | .hclk = 24000000, | 112 | .hclk = 24000000, |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c index c3993ac20542..3280ab33f88a 100644 --- a/drivers/mfd/tc6387xb.c +++ b/drivers/mfd/tc6387xb.c | |||
| @@ -75,7 +75,7 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc) | |||
| 75 | 75 | ||
| 76 | /*--------------------------------------------------------------------------*/ | 76 | /*--------------------------------------------------------------------------*/ |
| 77 | 77 | ||
| 78 | const static struct tmio_mmc_data tc6387xb_mmc_data = { | 78 | static struct tmio_mmc_data tc6387xb_mmc_data = { |
| 79 | .hclk = 24000000, | 79 | .hclk = 24000000, |
| 80 | }; | 80 | }; |
| 81 | 81 | ||
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c index 9d2abb5d6e2c..1429a7341a9a 100644 --- a/drivers/mfd/tc6393xb.c +++ b/drivers/mfd/tc6393xb.c | |||
| @@ -136,7 +136,7 @@ static int tc6393xb_nand_enable(struct platform_device *nand) | |||
| 136 | return 0; | 136 | return 0; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | const static struct tmio_mmc_data tc6393xb_mmc_data = { | 139 | static struct tmio_mmc_data tc6393xb_mmc_data = { |
| 140 | .hclk = 24000000, | 140 | .hclk = 24000000, |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index ec90e953adce..cd1008c19cd7 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c | |||
| @@ -647,7 +647,7 @@ static inline int __init unprotect_pm_master(void) | |||
| 647 | return e; | 647 | return e; |
| 648 | } | 648 | } |
| 649 | 649 | ||
| 650 | static void __init clocks_init(struct device *dev) | 650 | static void clocks_init(struct device *dev) |
| 651 | { | 651 | { |
| 652 | int e = 0; | 652 | int e = 0; |
| 653 | struct clk *osc; | 653 | struct clk *osc; |
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index aca2670afd78..bae61b22501c 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
| @@ -255,7 +255,7 @@ static int twl4030_irq_thread(void *data) | |||
| 255 | * thread. All we do here is acknowledge and mask the interrupt and wakeup | 255 | * thread. All we do here is acknowledge and mask the interrupt and wakeup |
| 256 | * the kernel thread. | 256 | * the kernel thread. |
| 257 | */ | 257 | */ |
| 258 | static void handle_twl4030_pih(unsigned int irq, irq_desc_t *desc) | 258 | static void handle_twl4030_pih(unsigned int irq, struct irq_desc *desc) |
| 259 | { | 259 | { |
| 260 | /* Acknowledge, clear *AND* mask the interrupt... */ | 260 | /* Acknowledge, clear *AND* mask the interrupt... */ |
| 261 | desc->chip->ack(irq); | 261 | desc->chip->ack(irq); |
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c index 9a4cc954cb7c..7ccc1eab98ab 100644 --- a/drivers/mfd/wm8350-regmap.c +++ b/drivers/mfd/wm8350-regmap.c | |||
| @@ -3186,7 +3186,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = { | |||
| 3186 | /* read write volatile */ | 3186 | /* read write volatile */ |
| 3187 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R0 - Reset/ID */ | 3187 | { 0xFFFF, 0xFFFF, 0xFFFF }, /* R0 - Reset/ID */ |
| 3188 | { 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */ | 3188 | { 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */ |
| 3189 | { 0x0000, 0x0000, 0x0000 }, /* R2 */ | 3189 | { 0x007F, 0x0000, 0x0000 }, /* R2 - ROM Mask ID */ |
| 3190 | { 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */ | 3190 | { 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */ |
| 3191 | { 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */ | 3191 | { 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */ |
| 3192 | { 0x80FF, 0x80FF, 0x8000 }, /* R5 - System Hibernate */ | 3192 | { 0x80FF, 0x80FF, 0x8000 }, /* R5 - System Hibernate */ |
| @@ -3411,7 +3411,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = { | |||
| 3411 | { 0x0000, 0x0000, 0x0000 }, /* R224 */ | 3411 | { 0x0000, 0x0000, 0x0000 }, /* R224 */ |
| 3412 | { 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */ | 3412 | { 0x8F3F, 0x0000, 0xFFFF }, /* R225 - DCDC/LDO status */ |
| 3413 | { 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */ | 3413 | { 0x0000, 0x0000, 0xFFFF }, /* R226 - Charger status */ |
| 3414 | { 0x0000, 0x0000, 0xFFFF }, /* R227 */ | 3414 | { 0x34FE, 0x0000, 0xFFFF }, /* R227 */ |
| 3415 | { 0x0000, 0x0000, 0x0000 }, /* R228 */ | 3415 | { 0x0000, 0x0000, 0x0000 }, /* R228 */ |
| 3416 | { 0x0000, 0x0000, 0x0000 }, /* R229 */ | 3416 | { 0x0000, 0x0000, 0x0000 }, /* R229 */ |
| 3417 | { 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */ | 3417 | { 0xFFFF, 0x1FFF, 0xFFFF }, /* R230 - GPIO Pin Status */ |
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 7c21bf791569..ecfc8bbe89b9 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
| @@ -460,7 +460,7 @@ static int __init wm8400_module_init(void) | |||
| 460 | 460 | ||
| 461 | return ret; | 461 | return ret; |
| 462 | } | 462 | } |
| 463 | module_init(wm8400_module_init); | 463 | subsys_initcall(wm8400_module_init); |
| 464 | 464 | ||
| 465 | static void __exit wm8400_module_exit(void) | 465 | static void __exit wm8400_module_exit(void) |
| 466 | { | 466 | { |
diff --git a/include/linux/mfd/ab3100.h b/include/linux/mfd/ab3100.h new file mode 100644 index 000000000000..7a3f316e3848 --- /dev/null +++ b/include/linux/mfd/ab3100.h | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2007-2009 ST-Ericsson AB | ||
| 3 | * License terms: GNU General Public License (GPL) version 2 | ||
| 4 | * AB3100 core access functions | ||
| 5 | * Author: Linus Walleij <linus.walleij@stericsson.com> | ||
| 6 | */ | ||
| 7 | |||
| 8 | #include <linux/device.h> | ||
| 9 | |||
| 10 | #ifndef MFD_AB3100_H | ||
| 11 | #define MFD_AB3100_H | ||
| 12 | |||
| 13 | #define ABUNKNOWN 0 | ||
| 14 | #define AB3000 1 | ||
| 15 | #define AB3100 2 | ||
| 16 | |||
| 17 | /* | ||
| 18 | * AB3100, EVENTA1, A2 and A3 event register flags | ||
| 19 | * these are catenated into a single 32-bit flag in the code | ||
| 20 | * for event notification broadcasts. | ||
| 21 | */ | ||
| 22 | #define AB3100_EVENTA1_ONSWA (0x01<<16) | ||
| 23 | #define AB3100_EVENTA1_ONSWB (0x02<<16) | ||
| 24 | #define AB3100_EVENTA1_ONSWC (0x04<<16) | ||
| 25 | #define AB3100_EVENTA1_DCIO (0x08<<16) | ||
| 26 | #define AB3100_EVENTA1_OVER_TEMP (0x10<<16) | ||
| 27 | #define AB3100_EVENTA1_SIM_OFF (0x20<<16) | ||
| 28 | #define AB3100_EVENTA1_VBUS (0x40<<16) | ||
| 29 | #define AB3100_EVENTA1_VSET_USB (0x80<<16) | ||
| 30 | |||
| 31 | #define AB3100_EVENTA2_READY_TX (0x01<<8) | ||
| 32 | #define AB3100_EVENTA2_READY_RX (0x02<<8) | ||
| 33 | #define AB3100_EVENTA2_OVERRUN_ERROR (0x04<<8) | ||
| 34 | #define AB3100_EVENTA2_FRAMING_ERROR (0x08<<8) | ||
| 35 | #define AB3100_EVENTA2_CHARG_OVERCURRENT (0x10<<8) | ||
| 36 | #define AB3100_EVENTA2_MIDR (0x20<<8) | ||
| 37 | #define AB3100_EVENTA2_BATTERY_REM (0x40<<8) | ||
| 38 | #define AB3100_EVENTA2_ALARM (0x80<<8) | ||
| 39 | |||
| 40 | #define AB3100_EVENTA3_ADC_TRIG5 (0x01) | ||
| 41 | #define AB3100_EVENTA3_ADC_TRIG4 (0x02) | ||
| 42 | #define AB3100_EVENTA3_ADC_TRIG3 (0x04) | ||
| 43 | #define AB3100_EVENTA3_ADC_TRIG2 (0x08) | ||
| 44 | #define AB3100_EVENTA3_ADC_TRIGVBAT (0x10) | ||
| 45 | #define AB3100_EVENTA3_ADC_TRIGVTX (0x20) | ||
| 46 | #define AB3100_EVENTA3_ADC_TRIG1 (0x40) | ||
| 47 | #define AB3100_EVENTA3_ADC_TRIG0 (0x80) | ||
| 48 | |||
| 49 | /* AB3100, STR register flags */ | ||
| 50 | #define AB3100_STR_ONSWA (0x01) | ||
| 51 | #define AB3100_STR_ONSWB (0x02) | ||
| 52 | #define AB3100_STR_ONSWC (0x04) | ||
| 53 | #define AB3100_STR_DCIO (0x08) | ||
| 54 | #define AB3100_STR_BOOT_MODE (0x10) | ||
| 55 | #define AB3100_STR_SIM_OFF (0x20) | ||
| 56 | #define AB3100_STR_BATT_REMOVAL (0x40) | ||
| 57 | #define AB3100_STR_VBUS (0x80) | ||
| 58 | |||
| 59 | /** | ||
| 60 | * struct ab3100 | ||
| 61 | * @access_mutex: lock out concurrent accesses to the AB3100 registers | ||
| 62 | * @dev: pointer to the containing device | ||
| 63 | * @i2c_client: I2C client for this chip | ||
| 64 | * @testreg_client: secondary client for test registers | ||
| 65 | * @chip_name: name of this chip variant | ||
| 66 | * @chip_id: 8 bit chip ID for this chip variant | ||
| 67 | * @work: an event handling worker | ||
| 68 | * @event_subscribers: event subscribers are listed here | ||
| 69 | * @startup_events: a copy of the first reading of the event registers | ||
| 70 | * @startup_events_read: whether the first events have been read | ||
| 71 | * | ||
| 72 | * This struct is PRIVATE and devices using it should NOT | ||
| 73 | * access ANY fields. It is used as a token for calling the | ||
| 74 | * AB3100 functions. | ||
| 75 | */ | ||
| 76 | struct ab3100 { | ||
| 77 | struct mutex access_mutex; | ||
| 78 | struct device *dev; | ||
| 79 | struct i2c_client *i2c_client; | ||
| 80 | struct i2c_client *testreg_client; | ||
| 81 | char chip_name[32]; | ||
| 82 | u8 chip_id; | ||
| 83 | struct work_struct work; | ||
| 84 | struct blocking_notifier_head event_subscribers; | ||
| 85 | u32 startup_events; | ||
| 86 | bool startup_events_read; | ||
| 87 | }; | ||
| 88 | |||
| 89 | int ab3100_set_register(struct ab3100 *ab3100, u8 reg, u8 regval); | ||
| 90 | int ab3100_get_register(struct ab3100 *ab3100, u8 reg, u8 *regval); | ||
| 91 | int ab3100_get_register_page(struct ab3100 *ab3100, | ||
| 92 | u8 first_reg, u8 *regvals, u8 numregs); | ||
| 93 | int ab3100_mask_and_set_register(struct ab3100 *ab3100, | ||
| 94 | u8 reg, u8 andmask, u8 ormask); | ||
| 95 | u8 ab3100_get_chip_type(struct ab3100 *ab3100); | ||
| 96 | int ab3100_event_register(struct ab3100 *ab3100, | ||
| 97 | struct notifier_block *nb); | ||
| 98 | int ab3100_event_unregister(struct ab3100 *ab3100, | ||
| 99 | struct notifier_block *nb); | ||
| 100 | int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100, | ||
| 101 | u32 *fatevent); | ||
| 102 | |||
| 103 | #endif | ||
diff --git a/include/linux/mfd/asic3.h b/include/linux/mfd/asic3.h index 322cd6deb9f0..de3c4ad19afb 100644 --- a/include/linux/mfd/asic3.h +++ b/include/linux/mfd/asic3.h | |||
| @@ -30,6 +30,13 @@ struct asic3_platform_data { | |||
| 30 | #define ASIC3_NUM_GPIOS 64 | 30 | #define ASIC3_NUM_GPIOS 64 |
| 31 | #define ASIC3_NR_IRQS ASIC3_NUM_GPIOS + 6 | 31 | #define ASIC3_NR_IRQS ASIC3_NUM_GPIOS + 6 |
| 32 | 32 | ||
| 33 | #define ASIC3_IRQ_LED0 64 | ||
| 34 | #define ASIC3_IRQ_LED1 65 | ||
| 35 | #define ASIC3_IRQ_LED2 66 | ||
| 36 | #define ASIC3_IRQ_SPI 67 | ||
| 37 | #define ASIC3_IRQ_SMBUS 68 | ||
| 38 | #define ASIC3_IRQ_OWM 69 | ||
| 39 | |||
| 33 | #define ASIC3_TO_GPIO(gpio) (NR_BUILTIN_GPIO + (gpio)) | 40 | #define ASIC3_TO_GPIO(gpio) (NR_BUILTIN_GPIO + (gpio)) |
| 34 | 41 | ||
| 35 | #define ASIC3_GPIO_BANK_A 0 | 42 | #define ASIC3_GPIO_BANK_A 0 |
| @@ -227,8 +234,8 @@ struct asic3_platform_data { | |||
| 227 | 234 | ||
| 228 | 235 | ||
| 229 | /* Basic control of the SD ASIC */ | 236 | /* Basic control of the SD ASIC */ |
| 230 | #define ASIC3_SDHWCTRL_Base 0x0E00 | 237 | #define ASIC3_SDHWCTRL_BASE 0x0E00 |
| 231 | #define ASIC3_SDHWCTRL_SDConf 0x00 | 238 | #define ASIC3_SDHWCTRL_SDCONF 0x00 |
| 232 | 239 | ||
| 233 | #define ASIC3_SDHWCTRL_SUSPEND (1 << 0) /* 1=suspend all SD operations */ | 240 | #define ASIC3_SDHWCTRL_SUSPEND (1 << 0) /* 1=suspend all SD operations */ |
| 234 | #define ASIC3_SDHWCTRL_CLKSEL (1 << 1) /* 1=SDICK, 0=HCLK */ | 241 | #define ASIC3_SDHWCTRL_CLKSEL (1 << 1) /* 1=SDICK, 0=HCLK */ |
| @@ -242,10 +249,10 @@ struct asic3_platform_data { | |||
| 242 | /* SD card power supply ctrl 1=enable */ | 249 | /* SD card power supply ctrl 1=enable */ |
| 243 | #define ASIC3_SDHWCTRL_SDPWR (1 << 6) | 250 | #define ASIC3_SDHWCTRL_SDPWR (1 << 6) |
| 244 | 251 | ||
| 245 | #define ASIC3_EXTCF_Base 0x1100 | 252 | #define ASIC3_EXTCF_BASE 0x1100 |
| 246 | 253 | ||
| 247 | #define ASIC3_EXTCF_Select 0x00 | 254 | #define ASIC3_EXTCF_SELECT 0x00 |
| 248 | #define ASIC3_EXTCF_Reset 0x04 | 255 | #define ASIC3_EXTCF_RESET 0x04 |
| 249 | 256 | ||
| 250 | #define ASIC3_EXTCF_SMOD0 (1 << 0) /* slot number of mode 0 */ | 257 | #define ASIC3_EXTCF_SMOD0 (1 << 0) /* slot number of mode 0 */ |
| 251 | #define ASIC3_EXTCF_SMOD1 (1 << 1) /* slot number of mode 1 */ | 258 | #define ASIC3_EXTCF_SMOD1 (1 << 1) /* slot number of mode 1 */ |
| @@ -279,222 +286,9 @@ struct asic3_platform_data { | |||
| 279 | * SDIO_CTRL Control registers for SDIO operations | 286 | * SDIO_CTRL Control registers for SDIO operations |
| 280 | * | 287 | * |
| 281 | *****************************************************************************/ | 288 | *****************************************************************************/ |
| 282 | #define ASIC3_SD_CONFIG_Base 0x0400 /* Assumes 32 bit addressing */ | 289 | #define ASIC3_SD_CONFIG_BASE 0x0400 /* Assumes 32 bit addressing */ |
| 283 | 290 | #define ASIC3_SD_CTRL_BASE 0x1000 | |
| 284 | #define ASIC3_SD_CONFIG_Command 0x08 /* R/W: Command */ | 291 | #define ASIC3_SDIO_CTRL_BASE 0x1200 |
| 285 | |||
| 286 | /* [0:8] SD Control Register Base Address */ | ||
| 287 | #define ASIC3_SD_CONFIG_Addr0 0x20 | ||
| 288 | |||
| 289 | /* [9:31] SD Control Register Base Address */ | ||
| 290 | #define ASIC3_SD_CONFIG_Addr1 0x24 | ||
| 291 | |||
| 292 | /* R/O: interrupt assigned to pin */ | ||
| 293 | #define ASIC3_SD_CONFIG_IntPin 0x78 | ||
| 294 | |||
| 295 | /* | ||
| 296 | * Set to 0x1f to clock SD controller, 0 otherwise. | ||
| 297 | * At 0x82 - Gated Clock Ctrl | ||
| 298 | */ | ||
| 299 | #define ASIC3_SD_CONFIG_ClkStop 0x80 | ||
| 300 | |||
| 301 | /* Control clock of SD controller */ | ||
| 302 | #define ASIC3_SD_CONFIG_ClockMode 0x84 | ||
| 303 | #define ASIC3_SD_CONFIG_SDHC_PinStatus 0x88 /* R/0: SD pins status */ | ||
| 304 | #define ASIC3_SD_CONFIG_SDHC_Power1 0x90 /* Power1 - manual pwr ctrl */ | ||
| 305 | |||
| 306 | /* auto power up after card inserted */ | ||
| 307 | #define ASIC3_SD_CONFIG_SDHC_Power2 0x92 | ||
| 308 | |||
| 309 | /* auto power down when card removed */ | ||
| 310 | #define ASIC3_SD_CONFIG_SDHC_Power3 0x94 | ||
| 311 | #define ASIC3_SD_CONFIG_SDHC_CardDetect 0x98 | ||
| 312 | #define ASIC3_SD_CONFIG_SDHC_Slot 0xA0 /* R/O: support slot number */ | ||
| 313 | #define ASIC3_SD_CONFIG_SDHC_ExtGateClk1 0x1E0 /* Not used */ | ||
| 314 | #define ASIC3_SD_CONFIG_SDHC_ExtGateClk2 0x1E2 /* Not used*/ | ||
| 315 | |||
| 316 | /* GPIO Output Reg. , at 0x1EA - GPIO Output Enable Reg. */ | ||
| 317 | #define ASIC3_SD_CONFIG_SDHC_GPIO_OutAndEnable 0x1E8 | ||
| 318 | #define ASIC3_SD_CONFIG_SDHC_GPIO_Status 0x1EC /* GPIO Status Reg. */ | ||
| 319 | |||
| 320 | /* Bit 1: double buffer/single buffer */ | ||
| 321 | #define ASIC3_SD_CONFIG_SDHC_ExtGateClk3 0x1F0 | ||
| 322 | |||
| 323 | /* Memory access enable (set to 1 to access SD Controller) */ | ||
| 324 | #define SD_CONFIG_COMMAND_MAE (1<<1) | ||
| 325 | |||
| 326 | #define SD_CONFIG_CLK_ENABLE_ALL 0x1f | ||
| 327 | |||
| 328 | #define SD_CONFIG_POWER1_PC_33V 0x0200 /* Set for 3.3 volts */ | ||
| 329 | #define SD_CONFIG_POWER1_PC_OFF 0x0000 /* Turn off power */ | ||
| 330 | |||
| 331 | /* two bits - number of cycles for card detection */ | ||
| 332 | #define SD_CONFIG_CARDDETECTMODE_CLK ((x) & 0x3) | ||
| 333 | |||
| 334 | |||
| 335 | #define ASIC3_SD_CTRL_Base 0x1000 | ||
| 336 | |||
| 337 | #define ASIC3_SD_CTRL_Cmd 0x00 | ||
| 338 | #define ASIC3_SD_CTRL_Arg0 0x08 | ||
| 339 | #define ASIC3_SD_CTRL_Arg1 0x0C | ||
| 340 | #define ASIC3_SD_CTRL_StopInternal 0x10 | ||
| 341 | #define ASIC3_SD_CTRL_TransferSectorCount 0x14 | ||
| 342 | #define ASIC3_SD_CTRL_Response0 0x18 | ||
| 343 | #define ASIC3_SD_CTRL_Response1 0x1C | ||
| 344 | #define ASIC3_SD_CTRL_Response2 0x20 | ||
| 345 | #define ASIC3_SD_CTRL_Response3 0x24 | ||
| 346 | #define ASIC3_SD_CTRL_Response4 0x28 | ||
| 347 | #define ASIC3_SD_CTRL_Response5 0x2C | ||
| 348 | #define ASIC3_SD_CTRL_Response6 0x30 | ||
| 349 | #define ASIC3_SD_CTRL_Response7 0x34 | ||
| 350 | #define ASIC3_SD_CTRL_CardStatus 0x38 | ||
| 351 | #define ASIC3_SD_CTRL_BufferCtrl 0x3C | ||
| 352 | #define ASIC3_SD_CTRL_IntMaskCard 0x40 | ||
| 353 | #define ASIC3_SD_CTRL_IntMaskBuffer 0x44 | ||
| 354 | #define ASIC3_SD_CTRL_CardClockCtrl 0x48 | ||
| 355 | #define ASIC3_SD_CTRL_MemCardXferDataLen 0x4C | ||
| 356 | #define ASIC3_SD_CTRL_MemCardOptionSetup 0x50 | ||
| 357 | #define ASIC3_SD_CTRL_ErrorStatus0 0x58 | ||
| 358 | #define ASIC3_SD_CTRL_ErrorStatus1 0x5C | ||
| 359 | #define ASIC3_SD_CTRL_DataPort 0x60 | ||
| 360 | #define ASIC3_SD_CTRL_TransactionCtrl 0x68 | ||
| 361 | #define ASIC3_SD_CTRL_SoftwareReset 0x1C0 | ||
| 362 | |||
| 363 | #define SD_CTRL_SOFTWARE_RESET_CLEAR (1<<0) | ||
| 364 | |||
| 365 | #define SD_CTRL_TRANSACTIONCONTROL_SET (1<<8) | ||
| 366 | |||
| 367 | #define SD_CTRL_CARDCLOCKCONTROL_FOR_SD_CARD (1<<15) | ||
| 368 | #define SD_CTRL_CARDCLOCKCONTROL_ENABLE_CLOCK (1<<8) | ||
| 369 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_512 (1<<7) | ||
| 370 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_256 (1<<6) | ||
| 371 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_128 (1<<5) | ||
| 372 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_64 (1<<4) | ||
| 373 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_32 (1<<3) | ||
| 374 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_16 (1<<2) | ||
| 375 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_8 (1<<1) | ||
| 376 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_4 (1<<0) | ||
| 377 | #define SD_CTRL_CARDCLOCKCONTROL_CLK_DIV_2 (0<<0) | ||
| 378 | |||
| 379 | #define MEM_CARD_OPTION_REQUIRED 0x000e | ||
| 380 | #define MEM_CARD_OPTION_DATA_RESPONSE_TIMEOUT(x) (((x) & 0x0f) << 4) | ||
| 381 | #define MEM_CARD_OPTION_C2_MODULE_NOT_PRESENT (1<<14) | ||
| 382 | #define MEM_CARD_OPTION_DATA_XFR_WIDTH_1 (1<<15) | ||
| 383 | #define MEM_CARD_OPTION_DATA_XFR_WIDTH_4 0 | ||
| 384 | |||
| 385 | #define SD_CTRL_COMMAND_INDEX(x) ((x) & 0x3f) | ||
| 386 | #define SD_CTRL_COMMAND_TYPE_CMD (0 << 6) | ||
| 387 | #define SD_CTRL_COMMAND_TYPE_ACMD (1 << 6) | ||
| 388 | #define SD_CTRL_COMMAND_TYPE_AUTHENTICATION (2 << 6) | ||
| 389 | #define SD_CTRL_COMMAND_RESPONSE_TYPE_NORMAL (0 << 8) | ||
| 390 | #define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1 (4 << 8) | ||
| 391 | #define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R1B (5 << 8) | ||
| 392 | #define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R2 (6 << 8) | ||
| 393 | #define SD_CTRL_COMMAND_RESPONSE_TYPE_EXT_R3 (7 << 8) | ||
| 394 | #define SD_CTRL_COMMAND_DATA_PRESENT (1 << 11) | ||
| 395 | #define SD_CTRL_COMMAND_TRANSFER_READ (1 << 12) | ||
| 396 | #define SD_CTRL_COMMAND_TRANSFER_WRITE (0 << 12) | ||
| 397 | #define SD_CTRL_COMMAND_MULTI_BLOCK (1 << 13) | ||
| 398 | #define SD_CTRL_COMMAND_SECURITY_CMD (1 << 14) | ||
| 399 | |||
| 400 | #define SD_CTRL_STOP_INTERNAL_ISSSUE_CMD12 (1 << 0) | ||
| 401 | #define SD_CTRL_STOP_INTERNAL_AUTO_ISSUE_CMD12 (1 << 8) | ||
| 402 | |||
| 403 | #define SD_CTRL_CARDSTATUS_RESPONSE_END (1 << 0) | ||
| 404 | #define SD_CTRL_CARDSTATUS_RW_END (1 << 2) | ||
| 405 | #define SD_CTRL_CARDSTATUS_CARD_REMOVED_0 (1 << 3) | ||
| 406 | #define SD_CTRL_CARDSTATUS_CARD_INSERTED_0 (1 << 4) | ||
| 407 | #define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_0 (1 << 5) | ||
| 408 | #define SD_CTRL_CARDSTATUS_WRITE_PROTECT (1 << 7) | ||
| 409 | #define SD_CTRL_CARDSTATUS_CARD_REMOVED_3 (1 << 8) | ||
| 410 | #define SD_CTRL_CARDSTATUS_CARD_INSERTED_3 (1 << 9) | ||
| 411 | #define SD_CTRL_CARDSTATUS_SIGNAL_STATE_PRESENT_3 (1 << 10) | ||
| 412 | |||
| 413 | #define SD_CTRL_BUFFERSTATUS_CMD_INDEX_ERROR (1 << 0) | ||
| 414 | #define SD_CTRL_BUFFERSTATUS_CRC_ERROR (1 << 1) | ||
| 415 | #define SD_CTRL_BUFFERSTATUS_STOP_BIT_END_ERROR (1 << 2) | ||
| 416 | #define SD_CTRL_BUFFERSTATUS_DATA_TIMEOUT (1 << 3) | ||
| 417 | #define SD_CTRL_BUFFERSTATUS_BUFFER_OVERFLOW (1 << 4) | ||
| 418 | #define SD_CTRL_BUFFERSTATUS_BUFFER_UNDERFLOW (1 << 5) | ||
| 419 | #define SD_CTRL_BUFFERSTATUS_CMD_TIMEOUT (1 << 6) | ||
| 420 | #define SD_CTRL_BUFFERSTATUS_UNK7 (1 << 7) | ||
| 421 | #define SD_CTRL_BUFFERSTATUS_BUFFER_READ_ENABLE (1 << 8) | ||
| 422 | #define SD_CTRL_BUFFERSTATUS_BUFFER_WRITE_ENABLE (1 << 9) | ||
| 423 | #define SD_CTRL_BUFFERSTATUS_ILLEGAL_FUNCTION (1 << 13) | ||
| 424 | #define SD_CTRL_BUFFERSTATUS_CMD_BUSY (1 << 14) | ||
| 425 | #define SD_CTRL_BUFFERSTATUS_ILLEGAL_ACCESS (1 << 15) | ||
| 426 | |||
| 427 | #define SD_CTRL_INTMASKCARD_RESPONSE_END (1 << 0) | ||
| 428 | #define SD_CTRL_INTMASKCARD_RW_END (1 << 2) | ||
| 429 | #define SD_CTRL_INTMASKCARD_CARD_REMOVED_0 (1 << 3) | ||
| 430 | #define SD_CTRL_INTMASKCARD_CARD_INSERTED_0 (1 << 4) | ||
| 431 | #define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_0 (1 << 5) | ||
| 432 | #define SD_CTRL_INTMASKCARD_UNK6 (1 << 6) | ||
| 433 | #define SD_CTRL_INTMASKCARD_WRITE_PROTECT (1 << 7) | ||
| 434 | #define SD_CTRL_INTMASKCARD_CARD_REMOVED_3 (1 << 8) | ||
| 435 | #define SD_CTRL_INTMASKCARD_CARD_INSERTED_3 (1 << 9) | ||
| 436 | #define SD_CTRL_INTMASKCARD_SIGNAL_STATE_PRESENT_3 (1 << 10) | ||
| 437 | |||
| 438 | #define SD_CTRL_INTMASKBUFFER_CMD_INDEX_ERROR (1 << 0) | ||
| 439 | #define SD_CTRL_INTMASKBUFFER_CRC_ERROR (1 << 1) | ||
| 440 | #define SD_CTRL_INTMASKBUFFER_STOP_BIT_END_ERROR (1 << 2) | ||
| 441 | #define SD_CTRL_INTMASKBUFFER_DATA_TIMEOUT (1 << 3) | ||
| 442 | #define SD_CTRL_INTMASKBUFFER_BUFFER_OVERFLOW (1 << 4) | ||
| 443 | #define SD_CTRL_INTMASKBUFFER_BUFFER_UNDERFLOW (1 << 5) | ||
| 444 | #define SD_CTRL_INTMASKBUFFER_CMD_TIMEOUT (1 << 6) | ||
| 445 | #define SD_CTRL_INTMASKBUFFER_UNK7 (1 << 7) | ||
| 446 | #define SD_CTRL_INTMASKBUFFER_BUFFER_READ_ENABLE (1 << 8) | ||
| 447 | #define SD_CTRL_INTMASKBUFFER_BUFFER_WRITE_ENABLE (1 << 9) | ||
| 448 | #define SD_CTRL_INTMASKBUFFER_ILLEGAL_FUNCTION (1 << 13) | ||
| 449 | #define SD_CTRL_INTMASKBUFFER_CMD_BUSY (1 << 14) | ||
| 450 | #define SD_CTRL_INTMASKBUFFER_ILLEGAL_ACCESS (1 << 15) | ||
| 451 | |||
| 452 | #define SD_CTRL_DETAIL0_RESPONSE_CMD_ERROR (1 << 0) | ||
| 453 | #define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 2) | ||
| 454 | #define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_RESPONSE_CMD12 (1 << 3) | ||
| 455 | #define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_READ_DATA (1 << 4) | ||
| 456 | #define SD_CTRL_DETAIL0_END_BIT_ERROR_FOR_WRITE_CRC_STATUS (1 << 5) | ||
| 457 | #define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_NON_CMD12 (1 << 8) | ||
| 458 | #define SD_CTRL_DETAIL0_CRC_ERROR_FOR_RESPONSE_CMD12 (1 << 9) | ||
| 459 | #define SD_CTRL_DETAIL0_CRC_ERROR_FOR_READ_DATA (1 << 10) | ||
| 460 | #define SD_CTRL_DETAIL0_CRC_ERROR_FOR_WRITE_CMD (1 << 11) | ||
| 461 | |||
| 462 | #define SD_CTRL_DETAIL1_NO_CMD_RESPONSE (1 << 0) | ||
| 463 | #define SD_CTRL_DETAIL1_TIMEOUT_READ_DATA (1 << 4) | ||
| 464 | #define SD_CTRL_DETAIL1_TIMEOUT_CRS_STATUS (1 << 5) | ||
| 465 | #define SD_CTRL_DETAIL1_TIMEOUT_CRC_BUSY (1 << 6) | ||
| 466 | |||
| 467 | #define ASIC3_SDIO_CTRL_Base 0x1200 | ||
| 468 | |||
| 469 | #define ASIC3_SDIO_CTRL_Cmd 0x00 | ||
| 470 | #define ASIC3_SDIO_CTRL_CardPortSel 0x04 | ||
| 471 | #define ASIC3_SDIO_CTRL_Arg0 0x08 | ||
| 472 | #define ASIC3_SDIO_CTRL_Arg1 0x0C | ||
| 473 | #define ASIC3_SDIO_CTRL_TransferBlockCount 0x14 | ||
| 474 | #define ASIC3_SDIO_CTRL_Response0 0x18 | ||
| 475 | #define ASIC3_SDIO_CTRL_Response1 0x1C | ||
| 476 | #define ASIC3_SDIO_CTRL_Response2 0x20 | ||
| 477 | #define ASIC3_SDIO_CTRL_Response3 0x24 | ||
| 478 | #define ASIC3_SDIO_CTRL_Response4 0x28 | ||
| 479 | #define ASIC3_SDIO_CTRL_Response5 0x2C | ||
| 480 | #define ASIC3_SDIO_CTRL_Response6 0x30 | ||
| 481 | #define ASIC3_SDIO_CTRL_Response7 0x34 | ||
| 482 | #define ASIC3_SDIO_CTRL_CardStatus 0x38 | ||
| 483 | #define ASIC3_SDIO_CTRL_BufferCtrl 0x3C | ||
| 484 | #define ASIC3_SDIO_CTRL_IntMaskCard 0x40 | ||
| 485 | #define ASIC3_SDIO_CTRL_IntMaskBuffer 0x44 | ||
| 486 | #define ASIC3_SDIO_CTRL_CardXferDataLen 0x4C | ||
| 487 | #define ASIC3_SDIO_CTRL_CardOptionSetup 0x50 | ||
| 488 | #define ASIC3_SDIO_CTRL_ErrorStatus0 0x54 | ||
| 489 | #define ASIC3_SDIO_CTRL_ErrorStatus1 0x58 | ||
| 490 | #define ASIC3_SDIO_CTRL_DataPort 0x60 | ||
| 491 | #define ASIC3_SDIO_CTRL_TransactionCtrl 0x68 | ||
| 492 | #define ASIC3_SDIO_CTRL_CardIntCtrl 0x6C | ||
| 493 | #define ASIC3_SDIO_CTRL_ClocknWaitCtrl 0x70 | ||
| 494 | #define ASIC3_SDIO_CTRL_HostInformation 0x74 | ||
| 495 | #define ASIC3_SDIO_CTRL_ErrorCtrl 0x78 | ||
| 496 | #define ASIC3_SDIO_CTRL_LEDCtrl 0x7C | ||
| 497 | #define ASIC3_SDIO_CTRL_SoftwareReset 0x1C0 | ||
| 498 | 292 | ||
| 499 | #define ASIC3_MAP_SIZE_32BIT 0x2000 | 293 | #define ASIC3_MAP_SIZE_32BIT 0x2000 |
| 500 | #define ASIC3_MAP_SIZE_16BIT 0x1000 | 294 | #define ASIC3_MAP_SIZE_16BIT 0x1000 |
diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h new file mode 100644 index 000000000000..c12c3c0932bf --- /dev/null +++ b/include/linux/mfd/ezx-pcap.h | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Daniel Ribeiro <drwyrm@gmail.com> | ||
| 3 | * | ||
| 4 | * For further information, please see http://wiki.openezx.org/PCAP2 | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef EZX_PCAP_H | ||
| 8 | #define EZX_PCAP_H | ||
| 9 | |||
| 10 | struct pcap_subdev { | ||
| 11 | int id; | ||
| 12 | const char *name; | ||
| 13 | void *platform_data; | ||
| 14 | }; | ||
| 15 | |||
| 16 | struct pcap_platform_data { | ||
| 17 | unsigned int irq_base; | ||
| 18 | unsigned int config; | ||
| 19 | void (*init) (void *); /* board specific init */ | ||
| 20 | int num_subdevs; | ||
| 21 | struct pcap_subdev *subdevs; | ||
| 22 | }; | ||
| 23 | |||
| 24 | struct pcap_chip; | ||
| 25 | |||
| 26 | int ezx_pcap_write(struct pcap_chip *, u8, u32); | ||
| 27 | int ezx_pcap_read(struct pcap_chip *, u8, u32 *); | ||
| 28 | int pcap_to_irq(struct pcap_chip *, int); | ||
| 29 | int pcap_adc_async(struct pcap_chip *, u8, u32, u8[], void *, void *); | ||
| 30 | int pcap_adc_sync(struct pcap_chip *, u8, u32, u8[], u16[]); | ||
| 31 | |||
| 32 | #define PCAP_SECOND_PORT 1 | ||
| 33 | #define PCAP_CS_AH 2 | ||
| 34 | |||
| 35 | #define PCAP_REGISTER_WRITE_OP_BIT 0x80000000 | ||
| 36 | #define PCAP_REGISTER_READ_OP_BIT 0x00000000 | ||
| 37 | |||
| 38 | #define PCAP_REGISTER_VALUE_MASK 0x01ffffff | ||
| 39 | #define PCAP_REGISTER_ADDRESS_MASK 0x7c000000 | ||
| 40 | #define PCAP_REGISTER_ADDRESS_SHIFT 26 | ||
| 41 | #define PCAP_REGISTER_NUMBER 32 | ||
| 42 | #define PCAP_CLEAR_INTERRUPT_REGISTER 0x01ffffff | ||
| 43 | #define PCAP_MASK_ALL_INTERRUPT 0x01ffffff | ||
| 44 | |||
| 45 | /* registers acessible by both pcap ports */ | ||
| 46 | #define PCAP_REG_ISR 0x0 /* Interrupt Status */ | ||
| 47 | #define PCAP_REG_MSR 0x1 /* Interrupt Mask */ | ||
| 48 | #define PCAP_REG_PSTAT 0x2 /* Processor Status */ | ||
| 49 | #define PCAP_REG_VREG2 0x6 /* Regulator Bank 2 Control */ | ||
| 50 | #define PCAP_REG_AUXVREG 0x7 /* Auxiliary Regulator Control */ | ||
| 51 | #define PCAP_REG_BATT 0x8 /* Battery Control */ | ||
| 52 | #define PCAP_REG_ADC 0x9 /* AD Control */ | ||
| 53 | #define PCAP_REG_ADR 0xa /* AD Result */ | ||
| 54 | #define PCAP_REG_CODEC 0xb /* Audio Codec Control */ | ||
| 55 | #define PCAP_REG_RX_AMPS 0xc /* RX Audio Amplifiers Control */ | ||
| 56 | #define PCAP_REG_ST_DAC 0xd /* Stereo DAC Control */ | ||
| 57 | #define PCAP_REG_BUSCTRL 0x14 /* Connectivity Control */ | ||
| 58 | #define PCAP_REG_PERIPH 0x15 /* Peripheral Control */ | ||
| 59 | #define PCAP_REG_LOWPWR 0x18 /* Regulator Low Power Control */ | ||
| 60 | #define PCAP_REG_TX_AMPS 0x1a /* TX Audio Amplifiers Control */ | ||
| 61 | #define PCAP_REG_GP 0x1b /* General Purpose */ | ||
| 62 | #define PCAP_REG_TEST1 0x1c | ||
| 63 | #define PCAP_REG_TEST2 0x1d | ||
| 64 | #define PCAP_REG_VENDOR_TEST1 0x1e | ||
| 65 | #define PCAP_REG_VENDOR_TEST2 0x1f | ||
| 66 | |||
| 67 | /* registers acessible by pcap port 1 only (a1200, e2 & e6) */ | ||
| 68 | #define PCAP_REG_INT_SEL 0x3 /* Interrupt Select */ | ||
| 69 | #define PCAP_REG_SWCTRL 0x4 /* Switching Regulator Control */ | ||
| 70 | #define PCAP_REG_VREG1 0x5 /* Regulator Bank 1 Control */ | ||
| 71 | #define PCAP_REG_RTC_TOD 0xe /* RTC Time of Day */ | ||
| 72 | #define PCAP_REG_RTC_TODA 0xf /* RTC Time of Day Alarm */ | ||
| 73 | #define PCAP_REG_RTC_DAY 0x10 /* RTC Day */ | ||
| 74 | #define PCAP_REG_RTC_DAYA 0x11 /* RTC Day Alarm */ | ||
| 75 | #define PCAP_REG_MTRTMR 0x12 /* AD Monitor Timer */ | ||
| 76 | #define PCAP_REG_PWR 0x13 /* Power Control */ | ||
| 77 | #define PCAP_REG_AUXVREG_MASK 0x16 /* Auxiliary Regulator Mask */ | ||
| 78 | #define PCAP_REG_VENDOR_REV 0x17 | ||
| 79 | #define PCAP_REG_PERIPH_MASK 0x19 /* Peripheral Mask */ | ||
| 80 | |||
| 81 | /* PCAP2 Interrupts */ | ||
| 82 | #define PCAP_NIRQS 23 | ||
| 83 | #define PCAP_IRQ_ADCDONE 0 /* ADC done port 1 */ | ||
| 84 | #define PCAP_IRQ_TS 1 /* Touch Screen */ | ||
| 85 | #define PCAP_IRQ_1HZ 2 /* 1HZ timer */ | ||
| 86 | #define PCAP_IRQ_WH 3 /* ADC above high limit */ | ||
| 87 | #define PCAP_IRQ_WL 4 /* ADC below low limit */ | ||
| 88 | #define PCAP_IRQ_TODA 5 /* Time of day alarm */ | ||
| 89 | #define PCAP_IRQ_USB4V 6 /* USB above 4V */ | ||
| 90 | #define PCAP_IRQ_ONOFF 7 /* On/Off button */ | ||
| 91 | #define PCAP_IRQ_ONOFF2 8 /* On/Off button 2 */ | ||
| 92 | #define PCAP_IRQ_USB1V 9 /* USB above 1V */ | ||
| 93 | #define PCAP_IRQ_MOBPORT 10 | ||
| 94 | #define PCAP_IRQ_MIC 11 /* Mic attach/HS button */ | ||
| 95 | #define PCAP_IRQ_HS 12 /* Headset attach */ | ||
| 96 | #define PCAP_IRQ_ST 13 | ||
| 97 | #define PCAP_IRQ_PC 14 /* Power Cut */ | ||
| 98 | #define PCAP_IRQ_WARM 15 | ||
| 99 | #define PCAP_IRQ_EOL 16 /* Battery End Of Life */ | ||
| 100 | #define PCAP_IRQ_CLK 17 | ||
| 101 | #define PCAP_IRQ_SYSRST 18 /* System Reset */ | ||
| 102 | #define PCAP_IRQ_DUMMY 19 | ||
| 103 | #define PCAP_IRQ_ADCDONE2 20 /* ADC done port 2 */ | ||
| 104 | #define PCAP_IRQ_SOFTRESET 21 | ||
| 105 | #define PCAP_IRQ_MNEXB 22 | ||
| 106 | |||
| 107 | /* voltage regulators */ | ||
| 108 | #define V1 0 | ||
| 109 | #define V2 1 | ||
| 110 | #define V3 2 | ||
| 111 | #define V4 3 | ||
| 112 | #define V5 4 | ||
| 113 | #define V6 5 | ||
| 114 | #define V7 6 | ||
| 115 | #define V8 7 | ||
| 116 | #define V9 8 | ||
| 117 | #define V10 9 | ||
| 118 | #define VAUX1 10 | ||
| 119 | #define VAUX2 11 | ||
| 120 | #define VAUX3 12 | ||
| 121 | #define VAUX4 13 | ||
| 122 | #define VSIM 14 | ||
| 123 | #define VSIM2 15 | ||
| 124 | #define VVIB 16 | ||
| 125 | #define SW1 17 | ||
| 126 | #define SW2 18 | ||
| 127 | #define SW3 19 | ||
| 128 | #define SW1S 20 | ||
| 129 | #define SW2S 21 | ||
| 130 | |||
| 131 | #define PCAP_BATT_DAC_MASK 0x000000ff | ||
| 132 | #define PCAP_BATT_DAC_SHIFT 0 | ||
| 133 | #define PCAP_BATT_B_FDBK (1 << 8) | ||
| 134 | #define PCAP_BATT_EXT_ISENSE (1 << 9) | ||
| 135 | #define PCAP_BATT_V_COIN_MASK 0x00003c00 | ||
| 136 | #define PCAP_BATT_V_COIN_SHIFT 10 | ||
| 137 | #define PCAP_BATT_I_COIN (1 << 14) | ||
| 138 | #define PCAP_BATT_COIN_CH_EN (1 << 15) | ||
| 139 | #define PCAP_BATT_EOL_SEL_MASK 0x000e0000 | ||
| 140 | #define PCAP_BATT_EOL_SEL_SHIFT 17 | ||
| 141 | #define PCAP_BATT_EOL_CMP_EN (1 << 20) | ||
| 142 | #define PCAP_BATT_BATT_DET_EN (1 << 21) | ||
| 143 | #define PCAP_BATT_THERMBIAS_CTRL (1 << 22) | ||
| 144 | |||
| 145 | #define PCAP_ADC_ADEN (1 << 0) | ||
| 146 | #define PCAP_ADC_RAND (1 << 1) | ||
| 147 | #define PCAP_ADC_AD_SEL1 (1 << 2) | ||
| 148 | #define PCAP_ADC_AD_SEL2 (1 << 3) | ||
| 149 | #define PCAP_ADC_ADA1_MASK 0x00000070 | ||
| 150 | #define PCAP_ADC_ADA1_SHIFT 4 | ||
| 151 | #define PCAP_ADC_ADA2_MASK 0x00000380 | ||
| 152 | #define PCAP_ADC_ADA2_SHIFT 7 | ||
| 153 | #define PCAP_ADC_ATO_MASK 0x00003c00 | ||
| 154 | #define PCAP_ADC_ATO_SHIFT 10 | ||
| 155 | #define PCAP_ADC_ATOX (1 << 14) | ||
| 156 | #define PCAP_ADC_MTR1 (1 << 15) | ||
| 157 | #define PCAP_ADC_MTR2 (1 << 16) | ||
| 158 | #define PCAP_ADC_TS_M_MASK 0x000e0000 | ||
| 159 | #define PCAP_ADC_TS_M_SHIFT 17 | ||
| 160 | #define PCAP_ADC_TS_REF_LOWPWR (1 << 20) | ||
| 161 | #define PCAP_ADC_TS_REFENB (1 << 21) | ||
| 162 | #define PCAP_ADC_BATT_I_POLARITY (1 << 22) | ||
| 163 | #define PCAP_ADC_BATT_I_ADC (1 << 23) | ||
| 164 | |||
| 165 | #define PCAP_ADC_BANK_0 0 | ||
| 166 | #define PCAP_ADC_BANK_1 1 | ||
| 167 | /* ADC bank 0 */ | ||
| 168 | #define PCAP_ADC_CH_COIN 0 | ||
| 169 | #define PCAP_ADC_CH_BATT 1 | ||
| 170 | #define PCAP_ADC_CH_BPLUS 2 | ||
| 171 | #define PCAP_ADC_CH_MOBPORTB 3 | ||
| 172 | #define PCAP_ADC_CH_TEMPERATURE 4 | ||
| 173 | #define PCAP_ADC_CH_CHARGER_ID 5 | ||
| 174 | #define PCAP_ADC_CH_AD6 6 | ||
| 175 | /* ADC bank 1 */ | ||
| 176 | #define PCAP_ADC_CH_AD7 0 | ||
| 177 | #define PCAP_ADC_CH_AD8 1 | ||
| 178 | #define PCAP_ADC_CH_AD9 2 | ||
| 179 | #define PCAP_ADC_CH_TS_X1 3 | ||
| 180 | #define PCAP_ADC_CH_TS_X2 4 | ||
| 181 | #define PCAP_ADC_CH_TS_Y1 5 | ||
| 182 | #define PCAP_ADC_CH_TS_Y2 6 | ||
| 183 | |||
| 184 | #define PCAP_ADC_T_NOW 0 | ||
| 185 | #define PCAP_ADC_T_IN_BURST 1 | ||
| 186 | #define PCAP_ADC_T_OUT_BURST 2 | ||
| 187 | |||
| 188 | #define PCAP_ADC_ATO_IN_BURST 6 | ||
| 189 | #define PCAP_ADC_ATO_OUT_BURST 0 | ||
| 190 | |||
| 191 | #define PCAP_ADC_TS_M_XY 1 | ||
| 192 | #define PCAP_ADC_TS_M_PRESSURE 2 | ||
| 193 | #define PCAP_ADC_TS_M_PLATE_X 3 | ||
| 194 | #define PCAP_ADC_TS_M_PLATE_Y 4 | ||
| 195 | #define PCAP_ADC_TS_M_STANDBY 5 | ||
| 196 | #define PCAP_ADC_TS_M_NONTS 6 | ||
| 197 | |||
| 198 | #define PCAP_ADR_ADD1_MASK 0x000003ff | ||
| 199 | #define PCAP_ADR_ADD1_SHIFT 0 | ||
| 200 | #define PCAP_ADR_ADD2_MASK 0x000ffc00 | ||
| 201 | #define PCAP_ADR_ADD2_SHIFT 10 | ||
| 202 | #define PCAP_ADR_ADINC1 (1 << 20) | ||
| 203 | #define PCAP_ADR_ADINC2 (1 << 21) | ||
| 204 | #define PCAP_ADR_ASC (1 << 22) | ||
| 205 | #define PCAP_ADR_ONESHOT (1 << 23) | ||
| 206 | |||
| 207 | #define PCAP_BUSCTRL_FSENB (1 << 0) | ||
| 208 | #define PCAP_BUSCTRL_USB_SUSPEND (1 << 1) | ||
| 209 | #define PCAP_BUSCTRL_USB_PU (1 << 2) | ||
| 210 | #define PCAP_BUSCTRL_USB_PD (1 << 3) | ||
| 211 | #define PCAP_BUSCTRL_VUSB_EN (1 << 4) | ||
| 212 | #define PCAP_BUSCTRL_USB_PS (1 << 5) | ||
| 213 | #define PCAP_BUSCTRL_VUSB_MSTR_EN (1 << 6) | ||
| 214 | #define PCAP_BUSCTRL_VBUS_PD_ENB (1 << 7) | ||
| 215 | #define PCAP_BUSCTRL_CURRLIM (1 << 8) | ||
| 216 | #define PCAP_BUSCTRL_RS232ENB (1 << 9) | ||
| 217 | #define PCAP_BUSCTRL_RS232_DIR (1 << 10) | ||
| 218 | #define PCAP_BUSCTRL_SE0_CONN (1 << 11) | ||
| 219 | #define PCAP_BUSCTRL_USB_PDM (1 << 12) | ||
| 220 | #define PCAP_BUSCTRL_BUS_PRI_ADJ (1 << 24) | ||
| 221 | |||
| 222 | /* leds */ | ||
| 223 | #define PCAP_LED0 0 | ||
| 224 | #define PCAP_LED1 1 | ||
| 225 | #define PCAP_BL0 2 | ||
| 226 | #define PCAP_BL1 3 | ||
| 227 | #define PCAP_VIB 4 | ||
| 228 | #define PCAP_LED_3MA 0 | ||
| 229 | #define PCAP_LED_4MA 1 | ||
| 230 | #define PCAP_LED_5MA 2 | ||
| 231 | #define PCAP_LED_9MA 3 | ||
| 232 | #define PCAP_LED_GPIO_VAL_MASK 0x00ffffff | ||
| 233 | #define PCAP_LED_GPIO_EN 0x01000000 | ||
| 234 | #define PCAP_LED_GPIO_INVERT 0x02000000 | ||
| 235 | #define PCAP_LED_T_MASK 0xf | ||
| 236 | #define PCAP_LED_C_MASK 0x3 | ||
| 237 | #define PCAP_BL_MASK 0x1f | ||
| 238 | #define PCAP_BL0_SHIFT 0 | ||
| 239 | #define PCAP_LED0_EN (1 << 5) | ||
| 240 | #define PCAP_LED1_EN (1 << 6) | ||
| 241 | #define PCAP_LED0_T_SHIFT 7 | ||
| 242 | #define PCAP_LED1_T_SHIFT 11 | ||
| 243 | #define PCAP_LED0_C_SHIFT 15 | ||
| 244 | #define PCAP_LED1_C_SHIFT 17 | ||
| 245 | #define PCAP_BL1_SHIFT 20 | ||
| 246 | #define PCAP_VIB_MASK 0x3 | ||
| 247 | #define PCAP_VIB_SHIFT 20 | ||
| 248 | #define PCAP_VIB_EN (1 << 19) | ||
| 249 | |||
| 250 | /* RTC */ | ||
| 251 | #define PCAP_RTC_DAY_MASK 0x3fff | ||
| 252 | #define PCAP_RTC_TOD_MASK 0xffff | ||
| 253 | #define PCAP_RTC_PC_MASK 0x7 | ||
| 254 | #define SEC_PER_DAY 86400 | ||
| 255 | |||
| 256 | #endif | ||
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h index c377118884e6..6b9c5d06690c 100644 --- a/include/linux/mfd/tmio.h +++ b/include/linux/mfd/tmio.h | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | * data for the MMC controller | 22 | * data for the MMC controller |
| 23 | */ | 23 | */ |
| 24 | struct tmio_mmc_data { | 24 | struct tmio_mmc_data { |
| 25 | unsigned int hclk; | 25 | const unsigned int hclk; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
