0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/io.h>
0017 #include <linux/irq.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/clk.h>
0020 #include <linux/err.h>
0021 #include <linux/mfd/core.h>
0022 #include <linux/mfd/tmio.h>
0023 #include <linux/mfd/tc6393xb.h>
0024 #include <linux/gpio/driver.h>
0025 #include <linux/gpio/machine.h>
0026 #include <linux/gpio/consumer.h>
0027 #include <linux/slab.h>
0028
0029 #define SCR_REVID 0x08
0030 #define SCR_ISR 0x50
0031 #define SCR_IMR 0x52
0032 #define SCR_IRR 0x54
0033 #define SCR_GPER 0x60
0034 #define SCR_GPI_SR(i) (0x64 + (i))
0035 #define SCR_GPI_IMR(i) (0x68 + (i))
0036 #define SCR_GPI_EDER(i) (0x6c + (i))
0037 #define SCR_GPI_LIR(i) (0x70 + (i))
0038 #define SCR_GPO_DSR(i) (0x78 + (i))
0039 #define SCR_GPO_DOECR(i) (0x7c + (i))
0040 #define SCR_GP_IARCR(i) (0x80 + (i))
0041 #define SCR_GP_IARLCR(i) (0x84 + (i))
0042 #define SCR_GPI_BCR(i) (0x88 + (i))
0043 #define SCR_GPA_IARCR 0x8c
0044 #define SCR_GPA_IARLCR 0x90
0045 #define SCR_GPA_BCR 0x94
0046 #define SCR_CCR 0x98
0047 #define SCR_PLL2CR 0x9a
0048 #define SCR_PLL1CR 0x9c
0049 #define SCR_DIARCR 0xa0
0050 #define SCR_DBOCR 0xa1
0051 #define SCR_FER 0xe0
0052 #define SCR_MCR 0xe4
0053 #define SCR_CONFIG 0xfc
0054 #define SCR_DEBUG 0xff
0055
0056 #define SCR_CCR_CK32K BIT(0)
0057 #define SCR_CCR_USBCK BIT(1)
0058 #define SCR_CCR_UNK1 BIT(4)
0059 #define SCR_CCR_MCLK_MASK (7 << 8)
0060 #define SCR_CCR_MCLK_OFF (0 << 8)
0061 #define SCR_CCR_MCLK_12 (1 << 8)
0062 #define SCR_CCR_MCLK_24 (2 << 8)
0063 #define SCR_CCR_MCLK_48 (3 << 8)
0064 #define SCR_CCR_HCLK_MASK (3 << 12)
0065 #define SCR_CCR_HCLK_24 (0 << 12)
0066 #define SCR_CCR_HCLK_48 (1 << 12)
0067
0068 #define SCR_FER_USBEN BIT(0)
0069 #define SCR_FER_LCDCVEN BIT(1)
0070 #define SCR_FER_SLCDEN BIT(2)
0071
0072 #define SCR_MCR_RDY_MASK (3 << 0)
0073 #define SCR_MCR_RDY_OPENDRAIN (0 << 0)
0074 #define SCR_MCR_RDY_TRISTATE (1 << 0)
0075 #define SCR_MCR_RDY_PUSHPULL (2 << 0)
0076 #define SCR_MCR_RDY_UNK BIT(2)
0077 #define SCR_MCR_RDY_EN BIT(3)
0078 #define SCR_MCR_INT_MASK (3 << 4)
0079 #define SCR_MCR_INT_OPENDRAIN (0 << 4)
0080 #define SCR_MCR_INT_TRISTATE (1 << 4)
0081 #define SCR_MCR_INT_PUSHPULL (2 << 4)
0082 #define SCR_MCR_INT_UNK BIT(6)
0083 #define SCR_MCR_INT_EN BIT(7)
0084
0085
0086 #define TC_GPIO_BIT(i) (1 << (i & 0x7))
0087
0088
0089
0090 struct tc6393xb {
0091 void __iomem *scr;
0092 struct device *dev;
0093
0094 struct gpio_chip gpio;
0095 struct gpio_desc *vcc_on;
0096
0097 struct clk *clk;
0098
0099 raw_spinlock_t lock;
0100
0101 struct {
0102 u8 fer;
0103 u16 ccr;
0104 u8 gpi_bcr[3];
0105 u8 gpo_dsr[3];
0106 u8 gpo_doecr[3];
0107 } suspend_state;
0108
0109 struct resource rscr;
0110 struct resource *iomem;
0111 int irq;
0112 int irq_base;
0113 };
0114
0115 enum {
0116 TC6393XB_CELL_NAND,
0117 TC6393XB_CELL_MMC,
0118 TC6393XB_CELL_OHCI,
0119 TC6393XB_CELL_FB,
0120 };
0121
0122
0123
0124 static int tc6393xb_nand_enable(struct platform_device *nand)
0125 {
0126 struct tc6393xb *tc6393xb = dev_get_drvdata(nand->dev.parent);
0127 unsigned long flags;
0128
0129 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0130
0131
0132 dev_dbg(nand->dev.parent, "SMD buffer on\n");
0133 tmio_iowrite8(0xff, tc6393xb->scr + SCR_GPI_BCR(1));
0134
0135 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0136
0137 return 0;
0138 }
0139
0140 static const struct resource tc6393xb_nand_resources[] = {
0141 {
0142 .start = 0x1000,
0143 .end = 0x1007,
0144 .flags = IORESOURCE_MEM,
0145 },
0146 {
0147 .start = 0x0100,
0148 .end = 0x01ff,
0149 .flags = IORESOURCE_MEM,
0150 },
0151 {
0152 .start = IRQ_TC6393_NAND,
0153 .end = IRQ_TC6393_NAND,
0154 .flags = IORESOURCE_IRQ,
0155 },
0156 };
0157
0158 static const struct resource tc6393xb_mmc_resources[] = {
0159 {
0160 .start = 0x800,
0161 .end = 0x9ff,
0162 .flags = IORESOURCE_MEM,
0163 },
0164 {
0165 .start = IRQ_TC6393_MMC,
0166 .end = IRQ_TC6393_MMC,
0167 .flags = IORESOURCE_IRQ,
0168 },
0169 };
0170
0171 static const struct resource tc6393xb_ohci_resources[] = {
0172 {
0173 .start = 0x3000,
0174 .end = 0x31ff,
0175 .flags = IORESOURCE_MEM,
0176 },
0177 {
0178 .start = 0x0300,
0179 .end = 0x03ff,
0180 .flags = IORESOURCE_MEM,
0181 },
0182 {
0183 .start = 0x010000,
0184 .end = 0x017fff,
0185 .flags = IORESOURCE_MEM,
0186 },
0187 {
0188 .start = 0x018000,
0189 .end = 0x01ffff,
0190 .flags = IORESOURCE_MEM,
0191 },
0192 {
0193 .start = IRQ_TC6393_OHCI,
0194 .end = IRQ_TC6393_OHCI,
0195 .flags = IORESOURCE_IRQ,
0196 },
0197 };
0198
0199 static const struct resource tc6393xb_fb_resources[] = {
0200 {
0201 .start = 0x5000,
0202 .end = 0x51ff,
0203 .flags = IORESOURCE_MEM,
0204 },
0205 {
0206 .start = 0x0500,
0207 .end = 0x05ff,
0208 .flags = IORESOURCE_MEM,
0209 },
0210 {
0211 .start = 0x100000,
0212 .end = 0x1fffff,
0213 .flags = IORESOURCE_MEM,
0214 },
0215 {
0216 .start = IRQ_TC6393_FB,
0217 .end = IRQ_TC6393_FB,
0218 .flags = IORESOURCE_IRQ,
0219 },
0220 };
0221
0222 static int tc6393xb_ohci_enable(struct platform_device *dev)
0223 {
0224 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
0225 unsigned long flags;
0226 u16 ccr;
0227 u8 fer;
0228
0229 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0230
0231 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
0232 ccr |= SCR_CCR_USBCK;
0233 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
0234
0235 fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
0236 fer |= SCR_FER_USBEN;
0237 tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
0238
0239 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0240
0241 return 0;
0242 }
0243
0244 static int tc6393xb_ohci_disable(struct platform_device *dev)
0245 {
0246 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
0247 unsigned long flags;
0248 u16 ccr;
0249 u8 fer;
0250
0251 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0252
0253 fer = tmio_ioread8(tc6393xb->scr + SCR_FER);
0254 fer &= ~SCR_FER_USBEN;
0255 tmio_iowrite8(fer, tc6393xb->scr + SCR_FER);
0256
0257 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
0258 ccr &= ~SCR_CCR_USBCK;
0259 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
0260
0261 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0262
0263 return 0;
0264 }
0265
0266 static int tc6393xb_ohci_suspend(struct platform_device *dev)
0267 {
0268 struct tc6393xb_platform_data *tcpd = dev_get_platdata(dev->dev.parent);
0269
0270
0271 if (tcpd->resume_restore)
0272 return -EBUSY;
0273
0274 return tc6393xb_ohci_disable(dev);
0275 }
0276
0277 static int tc6393xb_fb_enable(struct platform_device *dev)
0278 {
0279 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
0280 unsigned long flags;
0281 u16 ccr;
0282
0283 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0284
0285 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
0286 ccr &= ~SCR_CCR_MCLK_MASK;
0287 ccr |= SCR_CCR_MCLK_48;
0288 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
0289
0290 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0291
0292 return 0;
0293 }
0294
0295 static int tc6393xb_fb_disable(struct platform_device *dev)
0296 {
0297 struct tc6393xb *tc6393xb = dev_get_drvdata(dev->dev.parent);
0298 unsigned long flags;
0299 u16 ccr;
0300
0301 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0302
0303 ccr = tmio_ioread16(tc6393xb->scr + SCR_CCR);
0304 ccr &= ~SCR_CCR_MCLK_MASK;
0305 ccr |= SCR_CCR_MCLK_OFF;
0306 tmio_iowrite16(ccr, tc6393xb->scr + SCR_CCR);
0307
0308 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0309
0310 return 0;
0311 }
0312
0313 int tc6393xb_lcd_set_power(struct platform_device *fb, bool on)
0314 {
0315 struct tc6393xb *tc6393xb = dev_get_drvdata(fb->dev.parent);
0316 u8 fer;
0317 unsigned long flags;
0318
0319 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0320
0321 fer = ioread8(tc6393xb->scr + SCR_FER);
0322 if (on)
0323 fer |= SCR_FER_SLCDEN;
0324 else
0325 fer &= ~SCR_FER_SLCDEN;
0326 iowrite8(fer, tc6393xb->scr + SCR_FER);
0327
0328 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0329
0330 return 0;
0331 }
0332 EXPORT_SYMBOL(tc6393xb_lcd_set_power);
0333
0334 int tc6393xb_lcd_mode(struct platform_device *fb,
0335 const struct fb_videomode *mode) {
0336 struct tc6393xb *tc6393xb = dev_get_drvdata(fb->dev.parent);
0337 unsigned long flags;
0338
0339 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0340
0341 iowrite16(mode->pixclock, tc6393xb->scr + SCR_PLL1CR + 0);
0342 iowrite16(mode->pixclock >> 16, tc6393xb->scr + SCR_PLL1CR + 2);
0343
0344 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0345
0346 return 0;
0347 }
0348 EXPORT_SYMBOL(tc6393xb_lcd_mode);
0349
0350 static int tc6393xb_mmc_enable(struct platform_device *mmc)
0351 {
0352 struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
0353
0354 tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0,
0355 tc6393xb_mmc_resources[0].start & 0xfffe);
0356
0357 return 0;
0358 }
0359
0360 static int tc6393xb_mmc_resume(struct platform_device *mmc)
0361 {
0362 struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
0363
0364 tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0,
0365 tc6393xb_mmc_resources[0].start & 0xfffe);
0366
0367 return 0;
0368 }
0369
0370 static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state)
0371 {
0372 struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
0373
0374 tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state);
0375 }
0376
0377 static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state)
0378 {
0379 struct tc6393xb *tc6393xb = dev_get_drvdata(mmc->dev.parent);
0380
0381 tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state);
0382 }
0383
0384 static struct tmio_mmc_data tc6393xb_mmc_data = {
0385 .hclk = 24000000,
0386 .set_pwr = tc6393xb_mmc_pwr,
0387 .set_clk_div = tc6393xb_mmc_clk_div,
0388 };
0389
0390 static struct mfd_cell tc6393xb_cells[] = {
0391 [TC6393XB_CELL_NAND] = {
0392 .name = "tmio-nand",
0393 .enable = tc6393xb_nand_enable,
0394 .num_resources = ARRAY_SIZE(tc6393xb_nand_resources),
0395 .resources = tc6393xb_nand_resources,
0396 },
0397 [TC6393XB_CELL_MMC] = {
0398 .name = "tmio-mmc",
0399 .enable = tc6393xb_mmc_enable,
0400 .resume = tc6393xb_mmc_resume,
0401 .platform_data = &tc6393xb_mmc_data,
0402 .pdata_size = sizeof(tc6393xb_mmc_data),
0403 .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
0404 .resources = tc6393xb_mmc_resources,
0405 },
0406 [TC6393XB_CELL_OHCI] = {
0407 .name = "tmio-ohci",
0408 .num_resources = ARRAY_SIZE(tc6393xb_ohci_resources),
0409 .resources = tc6393xb_ohci_resources,
0410 .enable = tc6393xb_ohci_enable,
0411 .suspend = tc6393xb_ohci_suspend,
0412 .resume = tc6393xb_ohci_enable,
0413 .disable = tc6393xb_ohci_disable,
0414 },
0415 [TC6393XB_CELL_FB] = {
0416 .name = "tmio-fb",
0417 .num_resources = ARRAY_SIZE(tc6393xb_fb_resources),
0418 .resources = tc6393xb_fb_resources,
0419 .enable = tc6393xb_fb_enable,
0420 .suspend = tc6393xb_fb_disable,
0421 .resume = tc6393xb_fb_enable,
0422 .disable = tc6393xb_fb_disable,
0423 },
0424 };
0425
0426
0427
0428 static int tc6393xb_gpio_get(struct gpio_chip *chip,
0429 unsigned offset)
0430 {
0431 struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
0432
0433
0434 return !!(tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8))
0435 & TC_GPIO_BIT(offset));
0436 }
0437
0438 static void __tc6393xb_gpio_set(struct gpio_chip *chip,
0439 unsigned offset, int value)
0440 {
0441 struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
0442 u8 dsr;
0443
0444 dsr = tmio_ioread8(tc6393xb->scr + SCR_GPO_DSR(offset / 8));
0445 if (value)
0446 dsr |= TC_GPIO_BIT(offset);
0447 else
0448 dsr &= ~TC_GPIO_BIT(offset);
0449
0450 tmio_iowrite8(dsr, tc6393xb->scr + SCR_GPO_DSR(offset / 8));
0451 }
0452
0453 static void tc6393xb_gpio_set(struct gpio_chip *chip,
0454 unsigned offset, int value)
0455 {
0456 struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
0457 unsigned long flags;
0458
0459 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0460
0461 __tc6393xb_gpio_set(chip, offset, value);
0462
0463 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0464 }
0465
0466 static int tc6393xb_gpio_direction_input(struct gpio_chip *chip,
0467 unsigned offset)
0468 {
0469 struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
0470 unsigned long flags;
0471 u8 doecr;
0472
0473 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0474
0475 doecr = tmio_ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
0476 doecr &= ~TC_GPIO_BIT(offset);
0477 tmio_iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
0478
0479 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0480
0481 return 0;
0482 }
0483
0484 static int tc6393xb_gpio_direction_output(struct gpio_chip *chip,
0485 unsigned offset, int value)
0486 {
0487 struct tc6393xb *tc6393xb = gpiochip_get_data(chip);
0488 unsigned long flags;
0489 u8 doecr;
0490
0491 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0492
0493 __tc6393xb_gpio_set(chip, offset, value);
0494
0495 doecr = tmio_ioread8(tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
0496 doecr |= TC_GPIO_BIT(offset);
0497 tmio_iowrite8(doecr, tc6393xb->scr + SCR_GPO_DOECR(offset / 8));
0498
0499 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0500
0501 return 0;
0502 }
0503
0504
0505
0506
0507
0508 #define TOSA_GPIO_TG_ON 0
0509 #define TOSA_GPIO_L_MUTE 1
0510 #define TOSA_GPIO_BL_C20MA 3
0511 #define TOSA_GPIO_CARD_VCC_ON 4
0512 #define TOSA_GPIO_CHARGE_OFF 6
0513 #define TOSA_GPIO_CHARGE_OFF_JC 7
0514 #define TOSA_GPIO_BAT0_V_ON 9
0515 #define TOSA_GPIO_BAT1_V_ON 10
0516 #define TOSA_GPIO_BU_CHRG_ON 11
0517 #define TOSA_GPIO_BAT_SW_ON 12
0518 #define TOSA_GPIO_BAT0_TH_ON 14
0519 #define TOSA_GPIO_BAT1_TH_ON 15
0520
0521
0522 GPIO_LOOKUP_SINGLE(tosa_lcd_gpio_lookup, "spi2.0", "tc6393xb",
0523 TOSA_GPIO_TG_ON, "tg #pwr", GPIO_ACTIVE_HIGH);
0524
0525 GPIO_LOOKUP_SINGLE(tosa_lcd_bl_gpio_lookup, "i2c-tos-bl", "tc6393xb",
0526 TOSA_GPIO_BL_C20MA, "backlight", GPIO_ACTIVE_HIGH);
0527
0528 GPIO_LOOKUP_SINGLE(tosa_audio_gpio_lookup, "tosa-audio", "tc6393xb",
0529 TOSA_GPIO_L_MUTE, NULL, GPIO_ACTIVE_HIGH);
0530
0531 static struct gpiod_lookup_table tosa_battery_gpio_lookup = {
0532 .dev_id = "wm97xx-battery",
0533 .table = {
0534 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_CHARGE_OFF,
0535 "main charge off", GPIO_ACTIVE_HIGH),
0536 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_CHARGE_OFF_JC,
0537 "jacket charge off", GPIO_ACTIVE_HIGH),
0538 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT0_V_ON,
0539 "main battery", GPIO_ACTIVE_HIGH),
0540 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT1_V_ON,
0541 "jacket battery", GPIO_ACTIVE_HIGH),
0542 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BU_CHRG_ON,
0543 "backup battery", GPIO_ACTIVE_HIGH),
0544
0545 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT1_TH_ON,
0546 "main battery temp", GPIO_ACTIVE_HIGH),
0547 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT0_TH_ON,
0548 "jacket battery temp", GPIO_ACTIVE_HIGH),
0549 GPIO_LOOKUP("tc6393xb", TOSA_GPIO_BAT_SW_ON,
0550 "battery switch", GPIO_ACTIVE_HIGH),
0551 { },
0552 },
0553 };
0554
0555 static struct gpiod_lookup_table *tc6393xb_gpio_lookups[] = {
0556 &tosa_lcd_gpio_lookup,
0557 &tosa_lcd_bl_gpio_lookup,
0558 &tosa_audio_gpio_lookup,
0559 &tosa_battery_gpio_lookup,
0560 };
0561
0562 static int tc6393xb_register_gpio(struct tc6393xb *tc6393xb)
0563 {
0564 struct gpio_chip *gc = &tc6393xb->gpio;
0565 struct device *dev = tc6393xb->dev;
0566 int ret;
0567
0568 gc->label = "tc6393xb";
0569 gc->base = -1;
0570 gc->ngpio = 16;
0571 gc->set = tc6393xb_gpio_set;
0572 gc->get = tc6393xb_gpio_get;
0573 gc->direction_input = tc6393xb_gpio_direction_input;
0574 gc->direction_output = tc6393xb_gpio_direction_output;
0575
0576 ret = devm_gpiochip_add_data(dev, gc, tc6393xb);
0577 if (ret)
0578 return dev_err_probe(dev, ret, "failed to add GPIO chip\n");
0579
0580
0581 gpiod_add_lookup_tables(tc6393xb_gpio_lookups, ARRAY_SIZE(tc6393xb_gpio_lookups));
0582
0583
0584 tc6393xb->vcc_on = gpiochip_request_own_desc(gc, TOSA_GPIO_CARD_VCC_ON, "VCC ON",
0585 GPIO_ACTIVE_HIGH, GPIOD_OUT_HIGH);
0586 if (IS_ERR(tc6393xb->vcc_on))
0587 return dev_err_probe(dev, PTR_ERR(tc6393xb->vcc_on),
0588 "failed to request VCC ON GPIO\n");
0589
0590 return 0;
0591 }
0592
0593
0594
0595 static void tc6393xb_irq(struct irq_desc *desc)
0596 {
0597 struct tc6393xb *tc6393xb = irq_desc_get_handler_data(desc);
0598 unsigned int isr;
0599 unsigned int i, irq_base;
0600
0601 irq_base = tc6393xb->irq_base;
0602
0603 while ((isr = tmio_ioread8(tc6393xb->scr + SCR_ISR) &
0604 ~tmio_ioread8(tc6393xb->scr + SCR_IMR)))
0605 for (i = 0; i < TC6393XB_NR_IRQS; i++) {
0606 if (isr & (1 << i))
0607 generic_handle_irq(irq_base + i);
0608 }
0609 }
0610
0611 static void tc6393xb_irq_ack(struct irq_data *data)
0612 {
0613 }
0614
0615 static void tc6393xb_irq_mask(struct irq_data *data)
0616 {
0617 struct tc6393xb *tc6393xb = irq_data_get_irq_chip_data(data);
0618 unsigned long flags;
0619 u8 imr;
0620
0621 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0622 imr = tmio_ioread8(tc6393xb->scr + SCR_IMR);
0623 imr |= 1 << (data->irq - tc6393xb->irq_base);
0624 tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR);
0625 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0626 }
0627
0628 static void tc6393xb_irq_unmask(struct irq_data *data)
0629 {
0630 struct tc6393xb *tc6393xb = irq_data_get_irq_chip_data(data);
0631 unsigned long flags;
0632 u8 imr;
0633
0634 raw_spin_lock_irqsave(&tc6393xb->lock, flags);
0635 imr = tmio_ioread8(tc6393xb->scr + SCR_IMR);
0636 imr &= ~(1 << (data->irq - tc6393xb->irq_base));
0637 tmio_iowrite8(imr, tc6393xb->scr + SCR_IMR);
0638 raw_spin_unlock_irqrestore(&tc6393xb->lock, flags);
0639 }
0640
0641 static struct irq_chip tc6393xb_chip = {
0642 .name = "tc6393xb",
0643 .irq_ack = tc6393xb_irq_ack,
0644 .irq_mask = tc6393xb_irq_mask,
0645 .irq_unmask = tc6393xb_irq_unmask,
0646 };
0647
0648 static void tc6393xb_attach_irq(struct platform_device *dev)
0649 {
0650 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
0651 unsigned int irq, irq_base;
0652
0653 irq_base = tc6393xb->irq_base;
0654
0655 for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
0656 irq_set_chip_and_handler(irq, &tc6393xb_chip, handle_edge_irq);
0657 irq_set_chip_data(irq, tc6393xb);
0658 irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
0659 }
0660
0661 irq_set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
0662 irq_set_chained_handler_and_data(tc6393xb->irq, tc6393xb_irq,
0663 tc6393xb);
0664 }
0665
0666 static void tc6393xb_detach_irq(struct platform_device *dev)
0667 {
0668 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
0669 unsigned int irq, irq_base;
0670
0671 irq_set_chained_handler_and_data(tc6393xb->irq, NULL, NULL);
0672
0673 irq_base = tc6393xb->irq_base;
0674
0675 for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
0676 irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
0677 irq_set_chip(irq, NULL);
0678 irq_set_chip_data(irq, NULL);
0679 }
0680 }
0681
0682
0683
0684 static int tc6393xb_probe(struct platform_device *dev)
0685 {
0686 struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
0687 struct tc6393xb *tc6393xb;
0688 struct resource *iomem, *rscr;
0689 int ret;
0690
0691 iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
0692 if (!iomem)
0693 return -EINVAL;
0694
0695 tc6393xb = kzalloc(sizeof *tc6393xb, GFP_KERNEL);
0696 if (!tc6393xb) {
0697 ret = -ENOMEM;
0698 goto err_kzalloc;
0699 }
0700 tc6393xb->dev = &dev->dev;
0701
0702 raw_spin_lock_init(&tc6393xb->lock);
0703
0704 platform_set_drvdata(dev, tc6393xb);
0705
0706 ret = platform_get_irq(dev, 0);
0707 if (ret >= 0)
0708 tc6393xb->irq = ret;
0709 else
0710 goto err_noirq;
0711
0712 tc6393xb->iomem = iomem;
0713 tc6393xb->irq_base = tcpd->irq_base;
0714
0715 tc6393xb->clk = clk_get(&dev->dev, "CLK_CK3P6MI");
0716 if (IS_ERR(tc6393xb->clk)) {
0717 ret = PTR_ERR(tc6393xb->clk);
0718 goto err_clk_get;
0719 }
0720
0721 rscr = &tc6393xb->rscr;
0722 rscr->name = "tc6393xb-core";
0723 rscr->start = iomem->start;
0724 rscr->end = iomem->start + 0xff;
0725 rscr->flags = IORESOURCE_MEM;
0726
0727 ret = request_resource(iomem, rscr);
0728 if (ret)
0729 goto err_request_scr;
0730
0731 tc6393xb->scr = ioremap(rscr->start, resource_size(rscr));
0732 if (!tc6393xb->scr) {
0733 ret = -ENOMEM;
0734 goto err_ioremap;
0735 }
0736
0737 ret = clk_prepare_enable(tc6393xb->clk);
0738 if (ret)
0739 goto err_clk_enable;
0740
0741 ret = tcpd->enable(dev);
0742 if (ret)
0743 goto err_enable;
0744
0745 iowrite8(0, tc6393xb->scr + SCR_FER);
0746 iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
0747 iowrite16(SCR_CCR_UNK1 | SCR_CCR_HCLK_48,
0748 tc6393xb->scr + SCR_CCR);
0749 iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
0750 SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
0751 BIT(15), tc6393xb->scr + SCR_MCR);
0752 iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
0753 iowrite8(0, tc6393xb->scr + SCR_IRR);
0754 iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
0755
0756 printk(KERN_INFO "Toshiba tc6393xb revision %d at 0x%08lx, irq %d\n",
0757 tmio_ioread8(tc6393xb->scr + SCR_REVID),
0758 (unsigned long) iomem->start, tc6393xb->irq);
0759
0760 ret = tc6393xb_register_gpio(tc6393xb);
0761 if (ret)
0762 goto err_gpio_add;
0763
0764 tc6393xb_attach_irq(dev);
0765
0766 tc6393xb_cells[TC6393XB_CELL_NAND].platform_data = tcpd->nand_data;
0767 tc6393xb_cells[TC6393XB_CELL_NAND].pdata_size =
0768 sizeof(*tcpd->nand_data);
0769 tc6393xb_cells[TC6393XB_CELL_FB].platform_data = tcpd->fb_data;
0770 tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data);
0771
0772 ret = mfd_add_devices(&dev->dev, dev->id,
0773 tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
0774 iomem, tcpd->irq_base, NULL);
0775
0776 if (!ret)
0777 return 0;
0778
0779 tc6393xb_detach_irq(dev);
0780 err_gpio_add:
0781 tcpd->disable(dev);
0782 err_enable:
0783 clk_disable_unprepare(tc6393xb->clk);
0784 err_clk_enable:
0785 iounmap(tc6393xb->scr);
0786 err_ioremap:
0787 release_resource(&tc6393xb->rscr);
0788 err_request_scr:
0789 clk_put(tc6393xb->clk);
0790 err_noirq:
0791 err_clk_get:
0792 kfree(tc6393xb);
0793 err_kzalloc:
0794 return ret;
0795 }
0796
0797 static int tc6393xb_remove(struct platform_device *dev)
0798 {
0799 struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
0800 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
0801
0802 mfd_remove_devices(&dev->dev);
0803
0804 tc6393xb_detach_irq(dev);
0805
0806 tcpd->disable(dev);
0807 clk_disable_unprepare(tc6393xb->clk);
0808 iounmap(tc6393xb->scr);
0809 release_resource(&tc6393xb->rscr);
0810 clk_put(tc6393xb->clk);
0811 kfree(tc6393xb);
0812
0813 return 0;
0814 }
0815
0816 #ifdef CONFIG_PM
0817 static int tc6393xb_suspend(struct platform_device *dev, pm_message_t state)
0818 {
0819 struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
0820 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
0821 int i, ret;
0822
0823 tc6393xb->suspend_state.ccr = ioread16(tc6393xb->scr + SCR_CCR);
0824 tc6393xb->suspend_state.fer = ioread8(tc6393xb->scr + SCR_FER);
0825
0826 for (i = 0; i < 3; i++) {
0827 tc6393xb->suspend_state.gpo_dsr[i] =
0828 ioread8(tc6393xb->scr + SCR_GPO_DSR(i));
0829 tc6393xb->suspend_state.gpo_doecr[i] =
0830 ioread8(tc6393xb->scr + SCR_GPO_DOECR(i));
0831 tc6393xb->suspend_state.gpi_bcr[i] =
0832 ioread8(tc6393xb->scr + SCR_GPI_BCR(i));
0833 }
0834 ret = tcpd->suspend(dev);
0835 clk_disable_unprepare(tc6393xb->clk);
0836
0837 return ret;
0838 }
0839
0840 static int tc6393xb_resume(struct platform_device *dev)
0841 {
0842 struct tc6393xb_platform_data *tcpd = dev_get_platdata(&dev->dev);
0843 struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
0844 int ret;
0845 int i;
0846
0847 ret = clk_prepare_enable(tc6393xb->clk);
0848 if (ret)
0849 return ret;
0850
0851 ret = tcpd->resume(dev);
0852 if (ret)
0853 return ret;
0854
0855 if (!tcpd->resume_restore)
0856 return 0;
0857
0858 iowrite8(tc6393xb->suspend_state.fer, tc6393xb->scr + SCR_FER);
0859 iowrite16(tcpd->scr_pll2cr, tc6393xb->scr + SCR_PLL2CR);
0860 iowrite16(tc6393xb->suspend_state.ccr, tc6393xb->scr + SCR_CCR);
0861 iowrite16(SCR_MCR_RDY_OPENDRAIN | SCR_MCR_RDY_UNK | SCR_MCR_RDY_EN |
0862 SCR_MCR_INT_OPENDRAIN | SCR_MCR_INT_UNK | SCR_MCR_INT_EN |
0863 BIT(15), tc6393xb->scr + SCR_MCR);
0864 iowrite16(tcpd->scr_gper, tc6393xb->scr + SCR_GPER);
0865 iowrite8(0, tc6393xb->scr + SCR_IRR);
0866 iowrite8(0xbf, tc6393xb->scr + SCR_IMR);
0867
0868 for (i = 0; i < 3; i++) {
0869 iowrite8(tc6393xb->suspend_state.gpo_dsr[i],
0870 tc6393xb->scr + SCR_GPO_DSR(i));
0871 iowrite8(tc6393xb->suspend_state.gpo_doecr[i],
0872 tc6393xb->scr + SCR_GPO_DOECR(i));
0873 iowrite8(tc6393xb->suspend_state.gpi_bcr[i],
0874 tc6393xb->scr + SCR_GPI_BCR(i));
0875 }
0876
0877 return 0;
0878 }
0879 #else
0880 #define tc6393xb_suspend NULL
0881 #define tc6393xb_resume NULL
0882 #endif
0883
0884 static struct platform_driver tc6393xb_driver = {
0885 .probe = tc6393xb_probe,
0886 .remove = tc6393xb_remove,
0887 .suspend = tc6393xb_suspend,
0888 .resume = tc6393xb_resume,
0889
0890 .driver = {
0891 .name = "tc6393xb",
0892 },
0893 };
0894
0895 static int __init tc6393xb_init(void)
0896 {
0897 return platform_driver_register(&tc6393xb_driver);
0898 }
0899
0900 static void __exit tc6393xb_exit(void)
0901 {
0902 platform_driver_unregister(&tc6393xb_driver);
0903 }
0904
0905 subsys_initcall(tc6393xb_init);
0906 module_exit(tc6393xb_exit);
0907
0908 MODULE_LICENSE("GPL v2");
0909 MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
0910 MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
0911 MODULE_ALIAS("platform:tc6393xb");
0912