diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/Kconfig | 2 | ||||
-rw-r--r-- | drivers/dma/shdma.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/Kconfig | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 121 | ||||
-rw-r--r-- | drivers/serial/sh-sci.c | 42 | ||||
-rw-r--r-- | drivers/serial/sh-sci.h | 29 | ||||
-rw-r--r-- | drivers/sh/Makefile | 5 | ||||
-rw-r--r-- | drivers/video/Kconfig | 8 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/sh_mipi_dsi.c | 505 |
10 files changed, 664 insertions, 59 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9e01e96fee94..8344375dc015 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -128,7 +128,7 @@ config TXX9_DMAC | |||
128 | 128 | ||
129 | config SH_DMAE | 129 | config SH_DMAE |
130 | tristate "Renesas SuperH DMAC support" | 130 | tristate "Renesas SuperH DMAC support" |
131 | depends on SUPERH && SH_DMA | 131 | depends on (SUPERH && SH_DMA) || (ARM && ARCH_SHMOBILE) |
132 | depends on !SH_DMA_API | 132 | depends on !SH_DMA_API |
133 | select DMA_ENGINE | 133 | select DMA_ENGINE |
134 | help | 134 | help |
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index a2a519fd2a24..fb64cf36ba61 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
@@ -816,7 +816,7 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) | |||
816 | return ret; | 816 | return ret; |
817 | } | 817 | } |
818 | 818 | ||
819 | #if defined(CONFIG_CPU_SH4) | 819 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
820 | static irqreturn_t sh_dmae_err(int irq, void *data) | 820 | static irqreturn_t sh_dmae_err(int irq, void *data) |
821 | { | 821 | { |
822 | struct sh_dmae_device *shdev = (struct sh_dmae_device *)data; | 822 | struct sh_dmae_device *shdev = (struct sh_dmae_device *)data; |
@@ -1057,7 +1057,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1057 | /* Default transfer size of 32 bytes requires 32-byte alignment */ | 1057 | /* Default transfer size of 32 bytes requires 32-byte alignment */ |
1058 | shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; | 1058 | shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE; |
1059 | 1059 | ||
1060 | #if defined(CONFIG_CPU_SH4) | 1060 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
1061 | chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | 1061 | chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); |
1062 | 1062 | ||
1063 | if (!chanirq_res) | 1063 | if (!chanirq_res) |
@@ -1082,7 +1082,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1082 | 1082 | ||
1083 | #else | 1083 | #else |
1084 | chanirq_res = errirq_res; | 1084 | chanirq_res = errirq_res; |
1085 | #endif /* CONFIG_CPU_SH4 */ | 1085 | #endif /* CONFIG_CPU_SH4 || CONFIG_ARCH_SHMOBILE */ |
1086 | 1086 | ||
1087 | if (chanirq_res->start == chanirq_res->end && | 1087 | if (chanirq_res->start == chanirq_res->end && |
1088 | !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { | 1088 | !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { |
@@ -1129,7 +1129,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) | |||
1129 | chan_probe_err: | 1129 | chan_probe_err: |
1130 | sh_dmae_chan_remove(shdev); | 1130 | sh_dmae_chan_remove(shdev); |
1131 | eirqres: | 1131 | eirqres: |
1132 | #if defined(CONFIG_CPU_SH4) | 1132 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) |
1133 | free_irq(errirq, shdev); | 1133 | free_irq(errirq, shdev); |
1134 | eirq_err: | 1134 | eirq_err: |
1135 | #endif | 1135 | #endif |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index bceafbfa7268..29e01f6238a7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -549,7 +549,7 @@ config I2C_SH7760 | |||
549 | 549 | ||
550 | config I2C_SH_MOBILE | 550 | config I2C_SH_MOBILE |
551 | tristate "SuperH Mobile I2C Controller" | 551 | tristate "SuperH Mobile I2C Controller" |
552 | depends on SUPERH | 552 | depends on SUPERH || ARCH_SHMOBILE |
553 | help | 553 | help |
554 | If you say yes to this option, support will be included for the | 554 | If you say yes to this option, support will be included for the |
555 | built-in I2C interface on the Renesas SH-Mobile processor. | 555 | built-in I2C interface on the Renesas SH-Mobile processor. |
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index ffb405d7c6f2..598c49acaeb5 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -119,8 +119,10 @@ struct sh_mobile_i2c_data { | |||
119 | struct i2c_adapter adap; | 119 | struct i2c_adapter adap; |
120 | 120 | ||
121 | struct clk *clk; | 121 | struct clk *clk; |
122 | u_int8_t icic; | ||
122 | u_int8_t iccl; | 123 | u_int8_t iccl; |
123 | u_int8_t icch; | 124 | u_int8_t icch; |
125 | u_int8_t flags; | ||
124 | 126 | ||
125 | spinlock_t lock; | 127 | spinlock_t lock; |
126 | wait_queue_head_t wait; | 128 | wait_queue_head_t wait; |
@@ -129,15 +131,17 @@ struct sh_mobile_i2c_data { | |||
129 | int sr; | 131 | int sr; |
130 | }; | 132 | }; |
131 | 133 | ||
134 | #define IIC_FLAG_HAS_ICIC67 (1 << 0) | ||
135 | |||
132 | #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ | 136 | #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ |
133 | 137 | ||
134 | /* Register offsets */ | 138 | /* Register offsets */ |
135 | #define ICDR(pd) (pd->reg + 0x00) | 139 | #define ICDR 0x00 |
136 | #define ICCR(pd) (pd->reg + 0x04) | 140 | #define ICCR 0x04 |
137 | #define ICSR(pd) (pd->reg + 0x08) | 141 | #define ICSR 0x08 |
138 | #define ICIC(pd) (pd->reg + 0x0c) | 142 | #define ICIC 0x0c |
139 | #define ICCL(pd) (pd->reg + 0x10) | 143 | #define ICCL 0x10 |
140 | #define ICCH(pd) (pd->reg + 0x14) | 144 | #define ICCH 0x14 |
141 | 145 | ||
142 | /* Register bits */ | 146 | /* Register bits */ |
143 | #define ICCR_ICE 0x80 | 147 | #define ICCR_ICE 0x80 |
@@ -155,11 +159,32 @@ struct sh_mobile_i2c_data { | |||
155 | #define ICSR_WAIT 0x02 | 159 | #define ICSR_WAIT 0x02 |
156 | #define ICSR_DTE 0x01 | 160 | #define ICSR_DTE 0x01 |
157 | 161 | ||
162 | #define ICIC_ICCLB8 0x80 | ||
163 | #define ICIC_ICCHB8 0x40 | ||
158 | #define ICIC_ALE 0x08 | 164 | #define ICIC_ALE 0x08 |
159 | #define ICIC_TACKE 0x04 | 165 | #define ICIC_TACKE 0x04 |
160 | #define ICIC_WAITE 0x02 | 166 | #define ICIC_WAITE 0x02 |
161 | #define ICIC_DTEE 0x01 | 167 | #define ICIC_DTEE 0x01 |
162 | 168 | ||
169 | static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) | ||
170 | { | ||
171 | if (offs == ICIC) | ||
172 | data |= pd->icic; | ||
173 | |||
174 | iowrite8(data, pd->reg + offs); | ||
175 | } | ||
176 | |||
177 | static unsigned char iic_rd(struct sh_mobile_i2c_data *pd, int offs) | ||
178 | { | ||
179 | return ioread8(pd->reg + offs); | ||
180 | } | ||
181 | |||
182 | static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, | ||
183 | unsigned char set, unsigned char clr) | ||
184 | { | ||
185 | iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); | ||
186 | } | ||
187 | |||
163 | static void activate_ch(struct sh_mobile_i2c_data *pd) | 188 | static void activate_ch(struct sh_mobile_i2c_data *pd) |
164 | { | 189 | { |
165 | unsigned long i2c_clk; | 190 | unsigned long i2c_clk; |
@@ -187,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) | |||
187 | else | 212 | else |
188 | pd->iccl = (u_int8_t)(num/denom); | 213 | pd->iccl = (u_int8_t)(num/denom); |
189 | 214 | ||
215 | /* one more bit of ICCL in ICIC */ | ||
216 | if (pd->flags & IIC_FLAG_HAS_ICIC67) { | ||
217 | if ((num/denom) > 0xff) | ||
218 | pd->icic |= ICIC_ICCLB8; | ||
219 | else | ||
220 | pd->icic &= ~ICIC_ICCLB8; | ||
221 | } | ||
222 | |||
190 | /* Calculate the value for icch. From the data sheet: | 223 | /* Calculate the value for icch. From the data sheet: |
191 | icch = (p clock / transfer rate) * (H / (L + H)) */ | 224 | icch = (p clock / transfer rate) * (H / (L + H)) */ |
192 | num = i2c_clk * 4; | 225 | num = i2c_clk * 4; |
@@ -196,25 +229,33 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) | |||
196 | else | 229 | else |
197 | pd->icch = (u_int8_t)(num/denom); | 230 | pd->icch = (u_int8_t)(num/denom); |
198 | 231 | ||
232 | /* one more bit of ICCH in ICIC */ | ||
233 | if (pd->flags & IIC_FLAG_HAS_ICIC67) { | ||
234 | if ((num/denom) > 0xff) | ||
235 | pd->icic |= ICIC_ICCHB8; | ||
236 | else | ||
237 | pd->icic &= ~ICIC_ICCHB8; | ||
238 | } | ||
239 | |||
199 | /* Enable channel and configure rx ack */ | 240 | /* Enable channel and configure rx ack */ |
200 | iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); | 241 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); |
201 | 242 | ||
202 | /* Mask all interrupts */ | 243 | /* Mask all interrupts */ |
203 | iowrite8(0, ICIC(pd)); | 244 | iic_wr(pd, ICIC, 0); |
204 | 245 | ||
205 | /* Set the clock */ | 246 | /* Set the clock */ |
206 | iowrite8(pd->iccl, ICCL(pd)); | 247 | iic_wr(pd, ICCL, pd->iccl); |
207 | iowrite8(pd->icch, ICCH(pd)); | 248 | iic_wr(pd, ICCH, pd->icch); |
208 | } | 249 | } |
209 | 250 | ||
210 | static void deactivate_ch(struct sh_mobile_i2c_data *pd) | 251 | static void deactivate_ch(struct sh_mobile_i2c_data *pd) |
211 | { | 252 | { |
212 | /* Clear/disable interrupts */ | 253 | /* Clear/disable interrupts */ |
213 | iowrite8(0, ICSR(pd)); | 254 | iic_wr(pd, ICSR, 0); |
214 | iowrite8(0, ICIC(pd)); | 255 | iic_wr(pd, ICIC, 0); |
215 | 256 | ||
216 | /* Disable channel */ | 257 | /* Disable channel */ |
217 | iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); | 258 | iic_set_clr(pd, ICCR, 0, ICCR_ICE); |
218 | 259 | ||
219 | /* Disable clock and mark device as idle */ | 260 | /* Disable clock and mark device as idle */ |
220 | clk_disable(pd->clk); | 261 | clk_disable(pd->clk); |
@@ -233,35 +274,35 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, | |||
233 | 274 | ||
234 | switch (op) { | 275 | switch (op) { |
235 | case OP_START: /* issue start and trigger DTE interrupt */ | 276 | case OP_START: /* issue start and trigger DTE interrupt */ |
236 | iowrite8(0x94, ICCR(pd)); | 277 | iic_wr(pd, ICCR, 0x94); |
237 | break; | 278 | break; |
238 | case OP_TX_FIRST: /* disable DTE interrupt and write data */ | 279 | case OP_TX_FIRST: /* disable DTE interrupt and write data */ |
239 | iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE, ICIC(pd)); | 280 | iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
240 | iowrite8(data, ICDR(pd)); | 281 | iic_wr(pd, ICDR, data); |
241 | break; | 282 | break; |
242 | case OP_TX: /* write data */ | 283 | case OP_TX: /* write data */ |
243 | iowrite8(data, ICDR(pd)); | 284 | iic_wr(pd, ICDR, data); |
244 | break; | 285 | break; |
245 | case OP_TX_STOP: /* write data and issue a stop afterwards */ | 286 | case OP_TX_STOP: /* write data and issue a stop afterwards */ |
246 | iowrite8(data, ICDR(pd)); | 287 | iic_wr(pd, ICDR, data); |
247 | iowrite8(0x90, ICCR(pd)); | 288 | iic_wr(pd, ICCR, 0x90); |
248 | break; | 289 | break; |
249 | case OP_TX_TO_RX: /* select read mode */ | 290 | case OP_TX_TO_RX: /* select read mode */ |
250 | iowrite8(0x81, ICCR(pd)); | 291 | iic_wr(pd, ICCR, 0x81); |
251 | break; | 292 | break; |
252 | case OP_RX: /* just read data */ | 293 | case OP_RX: /* just read data */ |
253 | ret = ioread8(ICDR(pd)); | 294 | ret = iic_rd(pd, ICDR); |
254 | break; | 295 | break; |
255 | case OP_RX_STOP: /* enable DTE interrupt, issue stop */ | 296 | case OP_RX_STOP: /* enable DTE interrupt, issue stop */ |
256 | iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, | 297 | iic_wr(pd, ICIC, |
257 | ICIC(pd)); | 298 | ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
258 | iowrite8(0xc0, ICCR(pd)); | 299 | iic_wr(pd, ICCR, 0xc0); |
259 | break; | 300 | break; |
260 | case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ | 301 | case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ |
261 | iowrite8(ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE, | 302 | iic_wr(pd, ICIC, |
262 | ICIC(pd)); | 303 | ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
263 | ret = ioread8(ICDR(pd)); | 304 | ret = iic_rd(pd, ICDR); |
264 | iowrite8(0xc0, ICCR(pd)); | 305 | iic_wr(pd, ICCR, 0xc0); |
265 | break; | 306 | break; |
266 | } | 307 | } |
267 | 308 | ||
@@ -367,7 +408,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) | |||
367 | unsigned char sr; | 408 | unsigned char sr; |
368 | int wakeup; | 409 | int wakeup; |
369 | 410 | ||
370 | sr = ioread8(ICSR(pd)); | 411 | sr = iic_rd(pd, ICSR); |
371 | pd->sr |= sr; /* remember state */ | 412 | pd->sr |= sr; /* remember state */ |
372 | 413 | ||
373 | dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, | 414 | dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, |
@@ -376,7 +417,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) | |||
376 | 417 | ||
377 | if (sr & (ICSR_AL | ICSR_TACK)) { | 418 | if (sr & (ICSR_AL | ICSR_TACK)) { |
378 | /* don't interrupt transaction - continue to issue stop */ | 419 | /* don't interrupt transaction - continue to issue stop */ |
379 | iowrite8(sr & ~(ICSR_AL | ICSR_TACK), ICSR(pd)); | 420 | iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK)); |
380 | wakeup = 0; | 421 | wakeup = 0; |
381 | } else if (pd->msg->flags & I2C_M_RD) | 422 | } else if (pd->msg->flags & I2C_M_RD) |
382 | wakeup = sh_mobile_i2c_isr_rx(pd); | 423 | wakeup = sh_mobile_i2c_isr_rx(pd); |
@@ -384,7 +425,7 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) | |||
384 | wakeup = sh_mobile_i2c_isr_tx(pd); | 425 | wakeup = sh_mobile_i2c_isr_tx(pd); |
385 | 426 | ||
386 | if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ | 427 | if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ |
387 | iowrite8(sr & ~ICSR_WAIT, ICSR(pd)); | 428 | iic_wr(pd, ICSR, sr & ~ICSR_WAIT); |
388 | 429 | ||
389 | if (wakeup) { | 430 | if (wakeup) { |
390 | pd->sr |= SW_DONE; | 431 | pd->sr |= SW_DONE; |
@@ -402,21 +443,21 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) | |||
402 | } | 443 | } |
403 | 444 | ||
404 | /* Initialize channel registers */ | 445 | /* Initialize channel registers */ |
405 | iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); | 446 | iic_set_clr(pd, ICCR, 0, ICCR_ICE); |
406 | 447 | ||
407 | /* Enable channel and configure rx ack */ | 448 | /* Enable channel and configure rx ack */ |
408 | iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); | 449 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); |
409 | 450 | ||
410 | /* Set the clock */ | 451 | /* Set the clock */ |
411 | iowrite8(pd->iccl, ICCL(pd)); | 452 | iic_wr(pd, ICCL, pd->iccl); |
412 | iowrite8(pd->icch, ICCH(pd)); | 453 | iic_wr(pd, ICCH, pd->icch); |
413 | 454 | ||
414 | pd->msg = usr_msg; | 455 | pd->msg = usr_msg; |
415 | pd->pos = -1; | 456 | pd->pos = -1; |
416 | pd->sr = 0; | 457 | pd->sr = 0; |
417 | 458 | ||
418 | /* Enable all interrupts to begin with */ | 459 | /* Enable all interrupts to begin with */ |
419 | iowrite8(ICIC_WAITE | ICIC_ALE | ICIC_TACKE | ICIC_DTEE, ICIC(pd)); | 460 | iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); |
420 | return 0; | 461 | return 0; |
421 | } | 462 | } |
422 | 463 | ||
@@ -451,7 +492,7 @@ static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, | |||
451 | 492 | ||
452 | retry_count = 1000; | 493 | retry_count = 1000; |
453 | again: | 494 | again: |
454 | val = ioread8(ICSR(pd)); | 495 | val = iic_rd(pd, ICSR); |
455 | 496 | ||
456 | dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); | 497 | dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); |
457 | 498 | ||
@@ -576,6 +617,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
576 | goto err_irq; | 617 | goto err_irq; |
577 | } | 618 | } |
578 | 619 | ||
620 | /* The IIC blocks on SH-Mobile ARM processors | ||
621 | * come with two new bits in ICIC. | ||
622 | */ | ||
623 | if (size > 0x17) | ||
624 | pd->flags |= IIC_FLAG_HAS_ICIC67; | ||
625 | |||
579 | /* Enable Runtime PM for this device. | 626 | /* Enable Runtime PM for this device. |
580 | * | 627 | * |
581 | * Also tell the Runtime PM core to ignore children | 628 | * Also tell the Runtime PM core to ignore children |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 5f90fcd7d107..c291b3add1d2 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -346,6 +346,27 @@ static int scif_rxfill(struct uart_port *port) | |||
346 | return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; | 346 | return sci_in(port, SCFDR) & SCIF2_RFDC_MASK; |
347 | } | 347 | } |
348 | } | 348 | } |
349 | #elif defined(CONFIG_ARCH_SH7372) | ||
350 | static int scif_txfill(struct uart_port *port) | ||
351 | { | ||
352 | if (port->type == PORT_SCIFA) | ||
353 | return sci_in(port, SCFDR) >> 8; | ||
354 | else | ||
355 | return sci_in(port, SCTFDR); | ||
356 | } | ||
357 | |||
358 | static int scif_txroom(struct uart_port *port) | ||
359 | { | ||
360 | return port->fifosize - scif_txfill(port); | ||
361 | } | ||
362 | |||
363 | static int scif_rxfill(struct uart_port *port) | ||
364 | { | ||
365 | if (port->type == PORT_SCIFA) | ||
366 | return sci_in(port, SCFDR) & SCIF_RFDC_MASK; | ||
367 | else | ||
368 | return sci_in(port, SCRFDR); | ||
369 | } | ||
349 | #else | 370 | #else |
350 | static int scif_txfill(struct uart_port *port) | 371 | static int scif_txfill(struct uart_port *port) |
351 | { | 372 | { |
@@ -683,7 +704,7 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
683 | u16 ssr = sci_in(port, SCxSR); | 704 | u16 ssr = sci_in(port, SCxSR); |
684 | 705 | ||
685 | /* Disable future Rx interrupts */ | 706 | /* Disable future Rx interrupts */ |
686 | if (port->type == PORT_SCIFA) { | 707 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
687 | disable_irq_nosync(irq); | 708 | disable_irq_nosync(irq); |
688 | scr |= 0x4000; | 709 | scr |= 0x4000; |
689 | } else { | 710 | } else { |
@@ -928,7 +949,7 @@ static void sci_dma_tx_complete(void *arg) | |||
928 | 949 | ||
929 | if (!uart_circ_empty(xmit)) { | 950 | if (!uart_circ_empty(xmit)) { |
930 | schedule_work(&s->work_tx); | 951 | schedule_work(&s->work_tx); |
931 | } else if (port->type == PORT_SCIFA) { | 952 | } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
932 | u16 ctrl = sci_in(port, SCSCR); | 953 | u16 ctrl = sci_in(port, SCSCR); |
933 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | 954 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); |
934 | } | 955 | } |
@@ -1184,7 +1205,7 @@ static void sci_start_tx(struct uart_port *port) | |||
1184 | unsigned short ctrl; | 1205 | unsigned short ctrl; |
1185 | 1206 | ||
1186 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1207 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
1187 | if (port->type == PORT_SCIFA) { | 1208 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1188 | u16 new, scr = sci_in(port, SCSCR); | 1209 | u16 new, scr = sci_in(port, SCSCR); |
1189 | if (s->chan_tx) | 1210 | if (s->chan_tx) |
1190 | new = scr | 0x8000; | 1211 | new = scr | 0x8000; |
@@ -1197,7 +1218,7 @@ static void sci_start_tx(struct uart_port *port) | |||
1197 | s->cookie_tx < 0) | 1218 | s->cookie_tx < 0) |
1198 | schedule_work(&s->work_tx); | 1219 | schedule_work(&s->work_tx); |
1199 | #endif | 1220 | #endif |
1200 | if (!s->chan_tx || port->type == PORT_SCIFA) { | 1221 | if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1201 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1222 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1202 | ctrl = sci_in(port, SCSCR); | 1223 | ctrl = sci_in(port, SCSCR); |
1203 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); | 1224 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); |
@@ -1210,7 +1231,7 @@ static void sci_stop_tx(struct uart_port *port) | |||
1210 | 1231 | ||
1211 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1232 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
1212 | ctrl = sci_in(port, SCSCR); | 1233 | ctrl = sci_in(port, SCSCR); |
1213 | if (port->type == PORT_SCIFA) | 1234 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1214 | ctrl &= ~0x8000; | 1235 | ctrl &= ~0x8000; |
1215 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1236 | ctrl &= ~SCI_CTRL_FLAGS_TIE; |
1216 | sci_out(port, SCSCR, ctrl); | 1237 | sci_out(port, SCSCR, ctrl); |
@@ -1222,7 +1243,7 @@ static void sci_start_rx(struct uart_port *port) | |||
1222 | 1243 | ||
1223 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | 1244 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ |
1224 | ctrl |= sci_in(port, SCSCR); | 1245 | ctrl |= sci_in(port, SCSCR); |
1225 | if (port->type == PORT_SCIFA) | 1246 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1226 | ctrl &= ~0x4000; | 1247 | ctrl &= ~0x4000; |
1227 | sci_out(port, SCSCR, ctrl); | 1248 | sci_out(port, SCSCR, ctrl); |
1228 | } | 1249 | } |
@@ -1233,7 +1254,7 @@ static void sci_stop_rx(struct uart_port *port) | |||
1233 | 1254 | ||
1234 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | 1255 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ |
1235 | ctrl = sci_in(port, SCSCR); | 1256 | ctrl = sci_in(port, SCSCR); |
1236 | if (port->type == PORT_SCIFA) | 1257 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) |
1237 | ctrl &= ~0x4000; | 1258 | ctrl &= ~0x4000; |
1238 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1259 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); |
1239 | sci_out(port, SCSCR, ctrl); | 1260 | sci_out(port, SCSCR, ctrl); |
@@ -1271,7 +1292,7 @@ static void rx_timer_fn(unsigned long arg) | |||
1271 | struct uart_port *port = &s->port; | 1292 | struct uart_port *port = &s->port; |
1272 | u16 scr = sci_in(port, SCSCR); | 1293 | u16 scr = sci_in(port, SCSCR); |
1273 | 1294 | ||
1274 | if (port->type == PORT_SCIFA) { | 1295 | if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { |
1275 | scr &= ~0x4000; | 1296 | scr &= ~0x4000; |
1276 | enable_irq(s->irqs[1]); | 1297 | enable_irq(s->irqs[1]); |
1277 | } | 1298 | } |
@@ -1524,6 +1545,8 @@ static const char *sci_type(struct uart_port *port) | |||
1524 | return "scif"; | 1545 | return "scif"; |
1525 | case PORT_SCIFA: | 1546 | case PORT_SCIFA: |
1526 | return "scifa"; | 1547 | return "scifa"; |
1548 | case PORT_SCIFB: | ||
1549 | return "scifb"; | ||
1527 | } | 1550 | } |
1528 | 1551 | ||
1529 | return NULL; | 1552 | return NULL; |
@@ -1612,6 +1635,9 @@ static int __devinit sci_init_single(struct platform_device *dev, | |||
1612 | port->line = index; | 1635 | port->line = index; |
1613 | 1636 | ||
1614 | switch (p->type) { | 1637 | switch (p->type) { |
1638 | case PORT_SCIFB: | ||
1639 | port->fifosize = 256; | ||
1640 | break; | ||
1615 | case PORT_SCIFA: | 1641 | case PORT_SCIFA: |
1616 | port->fifosize = 64; | 1642 | port->fifosize = 64; |
1617 | break; | 1643 | break; |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f70c49f915fa..9b52f77a9305 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -322,7 +322,7 @@ | |||
322 | #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ | 322 | #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\ |
323 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | 323 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ |
324 | { \ | 324 | { \ |
325 | if (port->type == PORT_SCIF) { \ | 325 | if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ |
326 | SCI_IN(scif_size, scif_offset) \ | 326 | SCI_IN(scif_size, scif_offset) \ |
327 | } else { /* PORT_SCI or PORT_SCIFA */ \ | 327 | } else { /* PORT_SCI or PORT_SCIFA */ \ |
328 | SCI_IN(sci_size, sci_offset); \ | 328 | SCI_IN(sci_size, sci_offset); \ |
@@ -330,7 +330,7 @@ | |||
330 | } \ | 330 | } \ |
331 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ | 331 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ |
332 | { \ | 332 | { \ |
333 | if (port->type == PORT_SCIF) { \ | 333 | if (port->type == PORT_SCIF || port->type == PORT_SCIFB) { \ |
334 | SCI_OUT(scif_size, scif_offset, value) \ | 334 | SCI_OUT(scif_size, scif_offset, value) \ |
335 | } else { /* PORT_SCI or PORT_SCIFA */ \ | 335 | } else { /* PORT_SCI or PORT_SCIFA */ \ |
336 | SCI_OUT(sci_size, sci_offset, value); \ | 336 | SCI_OUT(sci_size, sci_offset, value); \ |
@@ -384,8 +384,12 @@ | |||
384 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 384 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
385 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 385 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
386 | defined(CONFIG_ARCH_SH7367) || \ | 386 | defined(CONFIG_ARCH_SH7367) || \ |
387 | defined(CONFIG_ARCH_SH7377) || \ | 387 | defined(CONFIG_ARCH_SH7377) |
388 | defined(CONFIG_ARCH_SH7372) | 388 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
389 | CPU_SCIF_FNS(name, scif_offset, scif_size) | ||
390 | #elif defined(CONFIG_ARCH_SH7372) | ||
391 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ | ||
392 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) | ||
389 | #define SCIF_FNS(name, scif_offset, scif_size) \ | 393 | #define SCIF_FNS(name, scif_offset, scif_size) \ |
390 | CPU_SCIF_FNS(name, scif_offset, scif_size) | 394 | CPU_SCIF_FNS(name, scif_offset, scif_size) |
391 | #else | 395 | #else |
@@ -422,8 +426,7 @@ | |||
422 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 426 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
423 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ | 427 | defined(CONFIG_CPU_SUBTYPE_SH7721) || \ |
424 | defined(CONFIG_ARCH_SH7367) || \ | 428 | defined(CONFIG_ARCH_SH7367) || \ |
425 | defined(CONFIG_ARCH_SH7377) || \ | 429 | defined(CONFIG_ARCH_SH7377) |
426 | defined(CONFIG_ARCH_SH7372) | ||
427 | 430 | ||
428 | SCIF_FNS(SCSMR, 0x00, 16) | 431 | SCIF_FNS(SCSMR, 0x00, 16) |
429 | SCIF_FNS(SCBRR, 0x04, 8) | 432 | SCIF_FNS(SCBRR, 0x04, 8) |
@@ -436,6 +439,20 @@ SCIF_FNS(SCFDR, 0x1c, 16) | |||
436 | SCIF_FNS(SCxTDR, 0x20, 8) | 439 | SCIF_FNS(SCxTDR, 0x20, 8) |
437 | SCIF_FNS(SCxRDR, 0x24, 8) | 440 | SCIF_FNS(SCxRDR, 0x24, 8) |
438 | SCIF_FNS(SCLSR, 0x00, 0) | 441 | SCIF_FNS(SCLSR, 0x00, 0) |
442 | #elif defined(CONFIG_ARCH_SH7372) | ||
443 | SCIF_FNS(SCSMR, 0x00, 16) | ||
444 | SCIF_FNS(SCBRR, 0x04, 8) | ||
445 | SCIF_FNS(SCSCR, 0x08, 16) | ||
446 | SCIF_FNS(SCTDSR, 0x0c, 16) | ||
447 | SCIF_FNS(SCFER, 0x10, 16) | ||
448 | SCIF_FNS(SCxSR, 0x14, 16) | ||
449 | SCIF_FNS(SCFCR, 0x18, 16) | ||
450 | SCIF_FNS(SCFDR, 0x1c, 16) | ||
451 | SCIF_FNS(SCTFDR, 0x38, 16) | ||
452 | SCIF_FNS(SCRFDR, 0x3c, 16) | ||
453 | SCIx_FNS(SCxTDR, 0x20, 8, 0x40, 8) | ||
454 | SCIx_FNS(SCxRDR, 0x24, 8, 0x60, 8) | ||
455 | SCIF_FNS(SCLSR, 0x00, 0) | ||
439 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | 456 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
440 | defined(CONFIG_CPU_SUBTYPE_SH7724) | 457 | defined(CONFIG_CPU_SUBTYPE_SH7724) |
441 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) | 458 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) |
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 78bb5127abd0..08fc653a825c 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
@@ -1,9 +1,10 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the SuperH specific drivers. | 2 | # Makefile for the SuperH specific drivers. |
3 | # | 3 | # |
4 | obj-y := clk.o intc.o | ||
5 | |||
4 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 6 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
5 | obj-$(CONFIG_MAPLE) += maple/ | 7 | obj-$(CONFIG_MAPLE) += maple/ |
8 | |||
6 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o | 9 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o |
7 | obj-$(CONFIG_SUPERH) += clk.o | ||
8 | obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o | 10 | obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o |
9 | obj-y += intc.o | ||
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3d94a1471724..a9f9e5eaa040 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1895,6 +1895,13 @@ config FB_W100 | |||
1895 | 1895 | ||
1896 | If unsure, say N. | 1896 | If unsure, say N. |
1897 | 1897 | ||
1898 | config SH_MIPI_DSI | ||
1899 | tristate | ||
1900 | depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | ||
1901 | |||
1902 | config SH_LCD_MIPI_DSI | ||
1903 | bool | ||
1904 | |||
1898 | config FB_SH_MOBILE_LCDC | 1905 | config FB_SH_MOBILE_LCDC |
1899 | tristate "SuperH Mobile LCDC framebuffer support" | 1906 | tristate "SuperH Mobile LCDC framebuffer support" |
1900 | depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK | 1907 | depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK |
@@ -1903,6 +1910,7 @@ config FB_SH_MOBILE_LCDC | |||
1903 | select FB_SYS_IMAGEBLIT | 1910 | select FB_SYS_IMAGEBLIT |
1904 | select FB_SYS_FOPS | 1911 | select FB_SYS_FOPS |
1905 | select FB_DEFERRED_IO | 1912 | select FB_DEFERRED_IO |
1913 | select SH_MIPI_DSI if SH_LCD_MIPI_DSI | ||
1906 | ---help--- | 1914 | ---help--- |
1907 | Frame buffer driver for the on-chip SH-Mobile LCD controller. | 1915 | Frame buffer driver for the on-chip SH-Mobile LCD controller. |
1908 | 1916 | ||
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ddc2af2ba45b..3c3bf867ef18 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -123,6 +123,7 @@ obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o | |||
123 | obj-$(CONFIG_FB_PS3) += ps3fb.o | 123 | obj-$(CONFIG_FB_PS3) += ps3fb.o |
124 | obj-$(CONFIG_FB_SM501) += sm501fb.o | 124 | obj-$(CONFIG_FB_SM501) += sm501fb.o |
125 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o | 125 | obj-$(CONFIG_FB_XILINX) += xilinxfb.o |
126 | obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o | ||
126 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o | 127 | obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o |
127 | obj-$(CONFIG_FB_OMAP) += omap/ | 128 | obj-$(CONFIG_FB_OMAP) += omap/ |
128 | obj-y += omap2/ | 129 | obj-y += omap2/ |
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c new file mode 100644 index 000000000000..017ae9f47d36 --- /dev/null +++ b/drivers/video/sh_mipi_dsi.c | |||
@@ -0,0 +1,505 @@ | |||
1 | /* | ||
2 | * Renesas SH-mobile MIPI DSI support | ||
3 | * | ||
4 | * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de> | ||
5 | * | ||
6 | * This is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of version 2 of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/types.h> | ||
19 | |||
20 | #include <video/mipi_display.h> | ||
21 | #include <video/sh_mipi_dsi.h> | ||
22 | #include <video/sh_mobile_lcdc.h> | ||
23 | |||
24 | #define CMTSRTCTR 0x80d0 | ||
25 | #define CMTSRTREQ 0x8070 | ||
26 | |||
27 | #define DSIINTE 0x0060 | ||
28 | |||
29 | /* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */ | ||
30 | #define MAX_SH_MIPI_DSI 2 | ||
31 | |||
32 | struct sh_mipi { | ||
33 | void __iomem *base; | ||
34 | struct clk *dsit_clk; | ||
35 | struct clk *dsip_clk; | ||
36 | }; | ||
37 | |||
38 | static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI]; | ||
39 | |||
40 | /* Protect the above array */ | ||
41 | static DEFINE_MUTEX(array_lock); | ||
42 | |||
43 | static struct sh_mipi *sh_mipi_by_handle(int handle) | ||
44 | { | ||
45 | if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0) | ||
46 | return NULL; | ||
47 | |||
48 | return mipi_dsi[handle]; | ||
49 | } | ||
50 | |||
51 | static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd, | ||
52 | u8 cmd, u8 param) | ||
53 | { | ||
54 | u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8); | ||
55 | int cnt = 100; | ||
56 | |||
57 | /* transmit a short packet to LCD panel */ | ||
58 | iowrite32(1 | data, mipi->base + 0x80d0); /* CMTSRTCTR */ | ||
59 | iowrite32(1, mipi->base + 0x8070); /* CMTSRTREQ */ | ||
60 | |||
61 | while ((ioread32(mipi->base + 0x8070) & 1) && --cnt) | ||
62 | udelay(1); | ||
63 | |||
64 | return cnt ? 0 : -ETIMEDOUT; | ||
65 | } | ||
66 | |||
67 | #define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \ | ||
68 | -EINVAL : (c) - 1) | ||
69 | |||
70 | static int sh_mipi_dcs(int handle, u8 cmd) | ||
71 | { | ||
72 | struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); | ||
73 | if (!mipi) | ||
74 | return -ENODEV; | ||
75 | return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0); | ||
76 | } | ||
77 | |||
78 | static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param) | ||
79 | { | ||
80 | struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle)); | ||
81 | if (!mipi) | ||
82 | return -ENODEV; | ||
83 | return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd, | ||
84 | param); | ||
85 | } | ||
86 | |||
87 | static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable) | ||
88 | { | ||
89 | /* | ||
90 | * enable LCDC data tx, transition to LPS after completion of each HS | ||
91 | * packet | ||
92 | */ | ||
93 | iowrite32(0x00000002 | enable, mipi->base + 0x8000); /* DTCTR */ | ||
94 | } | ||
95 | |||
96 | static void sh_mipi_shutdown(struct platform_device *pdev) | ||
97 | { | ||
98 | struct sh_mipi *mipi = platform_get_drvdata(pdev); | ||
99 | |||
100 | sh_mipi_dsi_enable(mipi, false); | ||
101 | } | ||
102 | |||
103 | static void mipi_display_on(void *arg) | ||
104 | { | ||
105 | struct sh_mipi *mipi = arg; | ||
106 | |||
107 | sh_mipi_dsi_enable(mipi, true); | ||
108 | } | ||
109 | |||
110 | static void mipi_display_off(void *arg) | ||
111 | { | ||
112 | struct sh_mipi *mipi = arg; | ||
113 | |||
114 | sh_mipi_dsi_enable(mipi, false); | ||
115 | } | ||
116 | |||
117 | static int __init sh_mipi_setup(struct sh_mipi *mipi, | ||
118 | struct sh_mipi_dsi_info *pdata) | ||
119 | { | ||
120 | void __iomem *base = mipi->base; | ||
121 | struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; | ||
122 | u32 pctype, datatype, pixfmt; | ||
123 | u32 linelength; | ||
124 | bool yuv; | ||
125 | |||
126 | /* Select data format */ | ||
127 | switch (pdata->data_format) { | ||
128 | case MIPI_RGB888: | ||
129 | pctype = 0; | ||
130 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | ||
131 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
132 | linelength = ch->lcd_cfg.xres * 3; | ||
133 | yuv = false; | ||
134 | break; | ||
135 | case MIPI_RGB565: | ||
136 | pctype = 1; | ||
137 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | ||
138 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
139 | linelength = ch->lcd_cfg.xres * 2; | ||
140 | yuv = false; | ||
141 | break; | ||
142 | case MIPI_RGB666_LP: | ||
143 | pctype = 2; | ||
144 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | ||
145 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
146 | linelength = ch->lcd_cfg.xres * 3; | ||
147 | yuv = false; | ||
148 | break; | ||
149 | case MIPI_RGB666: | ||
150 | pctype = 3; | ||
151 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | ||
152 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | ||
153 | linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; | ||
154 | yuv = false; | ||
155 | break; | ||
156 | case MIPI_BGR888: | ||
157 | pctype = 8; | ||
158 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24; | ||
159 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
160 | linelength = ch->lcd_cfg.xres * 3; | ||
161 | yuv = false; | ||
162 | break; | ||
163 | case MIPI_BGR565: | ||
164 | pctype = 9; | ||
165 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16; | ||
166 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
167 | linelength = ch->lcd_cfg.xres * 2; | ||
168 | yuv = false; | ||
169 | break; | ||
170 | case MIPI_BGR666_LP: | ||
171 | pctype = 0xa; | ||
172 | datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18; | ||
173 | pixfmt = MIPI_DCS_PIXEL_FMT_24BIT; | ||
174 | linelength = ch->lcd_cfg.xres * 3; | ||
175 | yuv = false; | ||
176 | break; | ||
177 | case MIPI_BGR666: | ||
178 | pctype = 0xb; | ||
179 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18; | ||
180 | pixfmt = MIPI_DCS_PIXEL_FMT_18BIT; | ||
181 | linelength = (ch->lcd_cfg.xres * 18 + 7) / 8; | ||
182 | yuv = false; | ||
183 | break; | ||
184 | case MIPI_YUYV: | ||
185 | pctype = 4; | ||
186 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | ||
187 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
188 | linelength = ch->lcd_cfg.xres * 2; | ||
189 | yuv = true; | ||
190 | break; | ||
191 | case MIPI_UYVY: | ||
192 | pctype = 5; | ||
193 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16; | ||
194 | pixfmt = MIPI_DCS_PIXEL_FMT_16BIT; | ||
195 | linelength = ch->lcd_cfg.xres * 2; | ||
196 | yuv = true; | ||
197 | break; | ||
198 | case MIPI_YUV420_L: | ||
199 | pctype = 6; | ||
200 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | ||
201 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | ||
202 | linelength = (ch->lcd_cfg.xres * 12 + 7) / 8; | ||
203 | yuv = true; | ||
204 | break; | ||
205 | case MIPI_YUV420: | ||
206 | pctype = 7; | ||
207 | datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12; | ||
208 | pixfmt = MIPI_DCS_PIXEL_FMT_12BIT; | ||
209 | /* Length of U/V line */ | ||
210 | linelength = (ch->lcd_cfg.xres + 1) / 2; | ||
211 | yuv = true; | ||
212 | break; | ||
213 | default: | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | if ((yuv && ch->interface_type != YUV422) || | ||
218 | (!yuv && ch->interface_type != RGB24)) | ||
219 | return -EINVAL; | ||
220 | |||
221 | /* reset DSI link */ | ||
222 | iowrite32(0x00000001, base); /* SYSCTRL */ | ||
223 | /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ | ||
224 | udelay(50); | ||
225 | iowrite32(0x00000000, base); /* SYSCTRL */ | ||
226 | |||
227 | /* setup DSI link */ | ||
228 | |||
229 | /* | ||
230 | * Default = ULPS enable | | ||
231 | * Contention detection enabled | | ||
232 | * EoT packet transmission enable | | ||
233 | * CRC check enable | | ||
234 | * ECC check enable | ||
235 | * additionally enable first two lanes | ||
236 | */ | ||
237 | iowrite32(0x00003703, base + 0x04); /* SYSCONF */ | ||
238 | /* | ||
239 | * T_wakeup = 0x7000 | ||
240 | * T_hs-trail = 3 | ||
241 | * T_hs-prepare = 3 | ||
242 | * T_clk-trail = 3 | ||
243 | * T_clk-prepare = 2 | ||
244 | */ | ||
245 | iowrite32(0x70003332, base + 0x08); /* TIMSET */ | ||
246 | /* no responses requested */ | ||
247 | iowrite32(0x00000000, base + 0x18); /* RESREQSET0 */ | ||
248 | /* request response to packets of type 0x28 */ | ||
249 | iowrite32(0x00000100, base + 0x1c); /* RESREQSET1 */ | ||
250 | /* High-speed transmission timeout, default 0xffffffff */ | ||
251 | iowrite32(0x0fffffff, base + 0x20); /* HSTTOVSET */ | ||
252 | /* LP reception timeout, default 0xffffffff */ | ||
253 | iowrite32(0x0fffffff, base + 0x24); /* LPRTOVSET */ | ||
254 | /* Turn-around timeout, default 0xffffffff */ | ||
255 | iowrite32(0x0fffffff, base + 0x28); /* TATOVSET */ | ||
256 | /* Peripheral reset timeout, default 0xffffffff */ | ||
257 | iowrite32(0x0fffffff, base + 0x2c); /* PRTOVSET */ | ||
258 | /* Enable timeout counters */ | ||
259 | iowrite32(0x00000f00, base + 0x30); /* DSICTRL */ | ||
260 | /* Interrupts not used, disable all */ | ||
261 | iowrite32(0, base + DSIINTE); | ||
262 | /* DSI-Tx bias on */ | ||
263 | iowrite32(0x00000001, base + 0x70); /* PHYCTRL */ | ||
264 | udelay(200); | ||
265 | /* Deassert resets, power on, set multiplier */ | ||
266 | iowrite32(0x03070b01, base + 0x70); /* PHYCTRL */ | ||
267 | |||
268 | /* setup l-bridge */ | ||
269 | |||
270 | /* | ||
271 | * Enable transmission of all packets, | ||
272 | * transmit LPS after each HS packet completion | ||
273 | */ | ||
274 | iowrite32(0x00000006, base + 0x8000); /* DTCTR */ | ||
275 | /* VSYNC width = 2 (<< 17) */ | ||
276 | iowrite32(0x00040000 | (pctype << 12) | datatype, base + 0x8020); /* VMCTR1 */ | ||
277 | /* | ||
278 | * Non-burst mode with sync pulses: VSE and HSE are output, | ||
279 | * HSA period allowed, no commands in LP | ||
280 | */ | ||
281 | iowrite32(0x00e00000, base + 0x8024); /* VMCTR2 */ | ||
282 | /* | ||
283 | * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see | ||
284 | * sh_mobile_lcdc_info.ch[0].lcd_cfg.xres), HSALEN = 1 - default | ||
285 | * (unused, since VMCTR2[HSABM] = 0) | ||
286 | */ | ||
287 | iowrite32(1 | (linelength << 16), base + 0x8028); /* VMLEN1 */ | ||
288 | |||
289 | msleep(5); | ||
290 | |||
291 | /* setup LCD panel */ | ||
292 | |||
293 | /* cf. drivers/video/omap/lcd_mipid.c */ | ||
294 | sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE); | ||
295 | msleep(120); | ||
296 | /* | ||
297 | * [7] - Page Address Mode | ||
298 | * [6] - Column Address Mode | ||
299 | * [5] - Page / Column Address Mode | ||
300 | * [4] - Display Device Line Refresh Order | ||
301 | * [3] - RGB/BGR Order | ||
302 | * [2] - Display Data Latch Data Order | ||
303 | * [1] - Flip Horizontal | ||
304 | * [0] - Flip Vertical | ||
305 | */ | ||
306 | sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00); | ||
307 | /* cf. set_data_lines() */ | ||
308 | sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT, | ||
309 | pixfmt << 4); | ||
310 | sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static int __init sh_mipi_probe(struct platform_device *pdev) | ||
316 | { | ||
317 | struct sh_mipi *mipi; | ||
318 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | ||
319 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
320 | unsigned long rate, f_current; | ||
321 | int idx = pdev->id, ret; | ||
322 | char dsip_clk[] = "dsi.p_clk"; | ||
323 | |||
324 | if (!res || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) | ||
325 | return -ENODEV; | ||
326 | |||
327 | mutex_lock(&array_lock); | ||
328 | if (idx < 0) | ||
329 | for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) | ||
330 | ; | ||
331 | |||
332 | if (idx == ARRAY_SIZE(mipi_dsi)) { | ||
333 | ret = -EBUSY; | ||
334 | goto efindslot; | ||
335 | } | ||
336 | |||
337 | mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); | ||
338 | if (!mipi) { | ||
339 | ret = -ENOMEM; | ||
340 | goto ealloc; | ||
341 | } | ||
342 | |||
343 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | ||
344 | dev_err(&pdev->dev, "MIPI register region already claimed\n"); | ||
345 | ret = -EBUSY; | ||
346 | goto ereqreg; | ||
347 | } | ||
348 | |||
349 | mipi->base = ioremap(res->start, resource_size(res)); | ||
350 | if (!mipi->base) { | ||
351 | ret = -ENOMEM; | ||
352 | goto emap; | ||
353 | } | ||
354 | |||
355 | mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); | ||
356 | if (IS_ERR(mipi->dsit_clk)) { | ||
357 | ret = PTR_ERR(mipi->dsit_clk); | ||
358 | goto eclktget; | ||
359 | } | ||
360 | |||
361 | f_current = clk_get_rate(mipi->dsit_clk); | ||
362 | /* 80MHz required by the datasheet */ | ||
363 | rate = clk_round_rate(mipi->dsit_clk, 80000000); | ||
364 | if (rate > 0 && rate != f_current) | ||
365 | ret = clk_set_rate(mipi->dsit_clk, rate); | ||
366 | else | ||
367 | ret = rate; | ||
368 | if (ret < 0) | ||
369 | goto esettrate; | ||
370 | |||
371 | dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); | ||
372 | |||
373 | sprintf(dsip_clk, "dsi%1.1dp_clk", idx); | ||
374 | mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk); | ||
375 | if (IS_ERR(mipi->dsip_clk)) { | ||
376 | ret = PTR_ERR(mipi->dsip_clk); | ||
377 | goto eclkpget; | ||
378 | } | ||
379 | |||
380 | f_current = clk_get_rate(mipi->dsip_clk); | ||
381 | /* Between 10 and 50MHz */ | ||
382 | rate = clk_round_rate(mipi->dsip_clk, 24000000); | ||
383 | if (rate > 0 && rate != f_current) | ||
384 | ret = clk_set_rate(mipi->dsip_clk, rate); | ||
385 | else | ||
386 | ret = rate; | ||
387 | if (ret < 0) | ||
388 | goto esetprate; | ||
389 | |||
390 | dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate); | ||
391 | |||
392 | msleep(10); | ||
393 | |||
394 | ret = clk_enable(mipi->dsit_clk); | ||
395 | if (ret < 0) | ||
396 | goto eclkton; | ||
397 | |||
398 | ret = clk_enable(mipi->dsip_clk); | ||
399 | if (ret < 0) | ||
400 | goto eclkpon; | ||
401 | |||
402 | mipi_dsi[idx] = mipi; | ||
403 | |||
404 | ret = sh_mipi_setup(mipi, pdata); | ||
405 | if (ret < 0) | ||
406 | goto emipisetup; | ||
407 | |||
408 | mutex_unlock(&array_lock); | ||
409 | platform_set_drvdata(pdev, mipi); | ||
410 | |||
411 | /* Set up LCDC callbacks */ | ||
412 | pdata->lcd_chan->board_cfg.board_data = mipi; | ||
413 | pdata->lcd_chan->board_cfg.display_on = mipi_display_on; | ||
414 | pdata->lcd_chan->board_cfg.display_off = mipi_display_off; | ||
415 | |||
416 | return 0; | ||
417 | |||
418 | emipisetup: | ||
419 | mipi_dsi[idx] = NULL; | ||
420 | clk_disable(mipi->dsip_clk); | ||
421 | eclkpon: | ||
422 | clk_disable(mipi->dsit_clk); | ||
423 | eclkton: | ||
424 | esetprate: | ||
425 | clk_put(mipi->dsip_clk); | ||
426 | eclkpget: | ||
427 | esettrate: | ||
428 | clk_put(mipi->dsit_clk); | ||
429 | eclktget: | ||
430 | iounmap(mipi->base); | ||
431 | emap: | ||
432 | release_mem_region(res->start, resource_size(res)); | ||
433 | ereqreg: | ||
434 | kfree(mipi); | ||
435 | ealloc: | ||
436 | efindslot: | ||
437 | mutex_unlock(&array_lock); | ||
438 | |||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | static int __exit sh_mipi_remove(struct platform_device *pdev) | ||
443 | { | ||
444 | struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data; | ||
445 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
446 | struct sh_mipi *mipi = platform_get_drvdata(pdev); | ||
447 | int i, ret; | ||
448 | |||
449 | mutex_lock(&array_lock); | ||
450 | |||
451 | for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++) | ||
452 | ; | ||
453 | |||
454 | if (i == ARRAY_SIZE(mipi_dsi)) { | ||
455 | ret = -EINVAL; | ||
456 | } else { | ||
457 | ret = 0; | ||
458 | mipi_dsi[i] = NULL; | ||
459 | } | ||
460 | |||
461 | mutex_unlock(&array_lock); | ||
462 | |||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | |||
466 | pdata->lcd_chan->board_cfg.display_on = NULL; | ||
467 | pdata->lcd_chan->board_cfg.display_off = NULL; | ||
468 | pdata->lcd_chan->board_cfg.board_data = NULL; | ||
469 | |||
470 | clk_disable(mipi->dsip_clk); | ||
471 | clk_disable(mipi->dsit_clk); | ||
472 | clk_put(mipi->dsit_clk); | ||
473 | clk_put(mipi->dsip_clk); | ||
474 | iounmap(mipi->base); | ||
475 | if (res) | ||
476 | release_mem_region(res->start, resource_size(res)); | ||
477 | platform_set_drvdata(pdev, NULL); | ||
478 | kfree(mipi); | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static struct platform_driver sh_mipi_driver = { | ||
484 | .remove = __exit_p(sh_mipi_remove), | ||
485 | .shutdown = sh_mipi_shutdown, | ||
486 | .driver = { | ||
487 | .name = "sh-mipi-dsi", | ||
488 | }, | ||
489 | }; | ||
490 | |||
491 | static int __init sh_mipi_init(void) | ||
492 | { | ||
493 | return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe); | ||
494 | } | ||
495 | module_init(sh_mipi_init); | ||
496 | |||
497 | static void __exit sh_mipi_exit(void) | ||
498 | { | ||
499 | platform_driver_unregister(&sh_mipi_driver); | ||
500 | } | ||
501 | module_exit(sh_mipi_exit); | ||
502 | |||
503 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | ||
504 | MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver"); | ||
505 | MODULE_LICENSE("GPL v2"); | ||