OSDN Git Service

[media] staging: st-cec: Use cec_get_drvdata()
[uclinux-h8/linux.git] / drivers / staging / media / st-cec / stih-cec.c
1 /*
2  * drivers/staging/media/st-cec/stih-cec.c
3  *
4  * STIH4xx CEC driver
5  * Copyright (C) STMicroelectronic SA 2016
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 as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  */
12 #include <linux/clk.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/module.h>
17 #include <linux/of.h>
18 #include <linux/platform_device.h>
19
20 #include <media/cec.h>
21
22 #define CEC_NAME        "stih-cec"
23
24 /* CEC registers  */
25 #define CEC_CLK_DIV           0x0
26 #define CEC_CTRL              0x4
27 #define CEC_IRQ_CTRL          0x8
28 #define CEC_STATUS            0xC
29 #define CEC_EXT_STATUS        0x10
30 #define CEC_TX_CTRL           0x14
31 #define CEC_FREE_TIME_THRESH  0x18
32 #define CEC_BIT_TOUT_THRESH   0x1C
33 #define CEC_BIT_PULSE_THRESH  0x20
34 #define CEC_DATA              0x24
35 #define CEC_TX_ARRAY_CTRL     0x28
36 #define CEC_CTRL2             0x2C
37 #define CEC_TX_ERROR_STS      0x30
38 #define CEC_ADDR_TABLE        0x34
39 #define CEC_DATA_ARRAY_CTRL   0x38
40 #define CEC_DATA_ARRAY_STATUS 0x3C
41 #define CEC_TX_DATA_BASE      0x40
42 #define CEC_TX_DATA_TOP       0x50
43 #define CEC_TX_DATA_SIZE      0x1
44 #define CEC_RX_DATA_BASE      0x54
45 #define CEC_RX_DATA_TOP       0x64
46 #define CEC_RX_DATA_SIZE      0x1
47
48 /* CEC_CTRL2 */
49 #define CEC_LINE_INACTIVE_EN   BIT(0)
50 #define CEC_AUTO_BUS_ERR_EN    BIT(1)
51 #define CEC_STOP_ON_ARB_ERR_EN BIT(2)
52 #define CEC_TX_REQ_WAIT_EN     BIT(3)
53
54 /* CEC_DATA_ARRAY_CTRL */
55 #define CEC_TX_ARRAY_EN          BIT(0)
56 #define CEC_RX_ARRAY_EN          BIT(1)
57 #define CEC_TX_ARRAY_RESET       BIT(2)
58 #define CEC_RX_ARRAY_RESET       BIT(3)
59 #define CEC_TX_N_OF_BYTES_IRQ_EN BIT(4)
60 #define CEC_TX_STOP_ON_NACK      BIT(7)
61
62 /* CEC_TX_ARRAY_CTRL */
63 #define CEC_TX_N_OF_BYTES  0x1F
64 #define CEC_TX_START       BIT(5)
65 #define CEC_TX_AUTO_SOM_EN BIT(6)
66 #define CEC_TX_AUTO_EOM_EN BIT(7)
67
68 /* CEC_IRQ_CTRL */
69 #define CEC_TX_DONE_IRQ_EN   BIT(0)
70 #define CEC_ERROR_IRQ_EN     BIT(2)
71 #define CEC_RX_DONE_IRQ_EN   BIT(3)
72 #define CEC_RX_SOM_IRQ_EN    BIT(4)
73 #define CEC_RX_EOM_IRQ_EN    BIT(5)
74 #define CEC_FREE_TIME_IRQ_EN BIT(6)
75 #define CEC_PIN_STS_IRQ_EN   BIT(7)
76
77 /* CEC_CTRL */
78 #define CEC_IN_FILTER_EN    BIT(0)
79 #define CEC_PWR_SAVE_EN     BIT(1)
80 #define CEC_EN              BIT(4)
81 #define CEC_ACK_CTRL        BIT(5)
82 #define CEC_RX_RESET_EN     BIT(6)
83 #define CEC_IGNORE_RX_ERROR BIT(7)
84
85 /* CEC_STATUS */
86 #define CEC_TX_DONE_STS       BIT(0)
87 #define CEC_TX_ACK_GET_STS    BIT(1)
88 #define CEC_ERROR_STS         BIT(2)
89 #define CEC_RX_DONE_STS       BIT(3)
90 #define CEC_RX_SOM_STS        BIT(4)
91 #define CEC_RX_EOM_STS        BIT(5)
92 #define CEC_FREE_TIME_IRQ_STS BIT(6)
93 #define CEC_PIN_STS           BIT(7)
94 #define CEC_SBIT_TOUT_STS     BIT(8)
95 #define CEC_DBIT_TOUT_STS     BIT(9)
96 #define CEC_LPULSE_ERROR_STS  BIT(10)
97 #define CEC_HPULSE_ERROR_STS  BIT(11)
98 #define CEC_TX_ERROR          BIT(12)
99 #define CEC_TX_ARB_ERROR      BIT(13)
100 #define CEC_RX_ERROR_MIN      BIT(14)
101 #define CEC_RX_ERROR_MAX      BIT(15)
102
103 /* Signal free time in bit periods (2.4ms) */
104 #define CEC_PRESENT_INIT_SFT 7
105 #define CEC_NEW_INIT_SFT     5
106 #define CEC_RETRANSMIT_SFT   3
107
108 /* Constants for CEC_BIT_TOUT_THRESH register */
109 #define CEC_SBIT_TOUT_47MS BIT(1)
110 #define CEC_SBIT_TOUT_48MS (BIT(0) | BIT(1))
111 #define CEC_SBIT_TOUT_50MS BIT(2)
112 #define CEC_DBIT_TOUT_27MS BIT(0)
113 #define CEC_DBIT_TOUT_28MS BIT(1)
114 #define CEC_DBIT_TOUT_29MS (BIT(0) | BIT(1))
115
116 /* Constants for CEC_BIT_PULSE_THRESH register */
117 #define CEC_BIT_LPULSE_03MS BIT(1)
118 #define CEC_BIT_HPULSE_03MS BIT(3)
119
120 /* Constants for CEC_DATA_ARRAY_STATUS register */
121 #define CEC_RX_N_OF_BYTES                     0x1F
122 #define CEC_TX_N_OF_BYTES_SENT                BIT(5)
123 #define CEC_RX_OVERRUN                        BIT(6)
124
125 struct stih_cec {
126         struct cec_adapter      *adap;
127         struct device           *dev;
128         struct clk              *clk;
129         void __iomem            *regs;
130         int                     irq;
131         u32                     irq_status;
132 };
133
134 static int stih_cec_adap_enable(struct cec_adapter *adap, bool enable)
135 {
136         struct stih_cec *cec = cec_get_drvdata(adap);
137
138         if (enable) {
139                 /* The doc says (input TCLK_PERIOD * CEC_CLK_DIV) = 0.1ms */
140                 unsigned long clk_freq = clk_get_rate(cec->clk);
141                 u32 cec_clk_div = clk_freq / 10000;
142
143                 writel(cec_clk_div, cec->regs + CEC_CLK_DIV);
144
145                 /* Configuration of the durations activating a timeout */
146                 writel(CEC_SBIT_TOUT_47MS | (CEC_DBIT_TOUT_28MS << 4),
147                        cec->regs + CEC_BIT_TOUT_THRESH);
148
149                 /* Configuration of the smallest allowed duration for pulses */
150                 writel(CEC_BIT_LPULSE_03MS | CEC_BIT_HPULSE_03MS,
151                        cec->regs + CEC_BIT_PULSE_THRESH);
152
153                 /* Minimum received bit period threshold */
154                 writel(BIT(5) | BIT(7), cec->regs + CEC_TX_CTRL);
155
156                 /* Configuration of transceiver data arrays */
157                 writel(CEC_TX_ARRAY_EN | CEC_RX_ARRAY_EN | CEC_TX_STOP_ON_NACK,
158                        cec->regs + CEC_DATA_ARRAY_CTRL);
159
160                 /* Configuration of the control bits for CEC Transceiver */
161                 writel(CEC_IN_FILTER_EN | CEC_EN | CEC_RX_RESET_EN,
162                        cec->regs + CEC_CTRL);
163
164                 /* Clear logical addresses */
165                 writel(0, cec->regs + CEC_ADDR_TABLE);
166
167                 /* Clear the status register */
168                 writel(0x0, cec->regs + CEC_STATUS);
169
170                 /* Enable the interrupts */
171                 writel(CEC_TX_DONE_IRQ_EN | CEC_RX_DONE_IRQ_EN |
172                        CEC_RX_SOM_IRQ_EN | CEC_RX_EOM_IRQ_EN |
173                        CEC_ERROR_IRQ_EN,
174                        cec->regs + CEC_IRQ_CTRL);
175
176         } else {
177                 /* Clear logical addresses */
178                 writel(0, cec->regs + CEC_ADDR_TABLE);
179
180                 /* Clear the status register */
181                 writel(0x0, cec->regs + CEC_STATUS);
182
183                 /* Disable the interrupts */
184                 writel(0, cec->regs + CEC_IRQ_CTRL);
185         }
186
187         return 0;
188 }
189
190 static int stih_cec_adap_log_addr(struct cec_adapter *adap, u8 logical_addr)
191 {
192         struct stih_cec *cec = cec_get_drvdata(adap);
193         u32 reg = readl(cec->regs + CEC_ADDR_TABLE);
194
195         reg |= 1 << logical_addr;
196
197         if (logical_addr == CEC_LOG_ADDR_INVALID)
198                 reg = 0;
199
200         writel(reg, cec->regs + CEC_ADDR_TABLE);
201
202         return 0;
203 }
204
205 static int stih_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
206                                   u32 signal_free_time, struct cec_msg *msg)
207 {
208         struct stih_cec *cec = cec_get_drvdata(adap);
209         int i;
210
211         /* Copy message into registers */
212         for (i = 0; i < msg->len; i++)
213                 writeb(msg->msg[i], cec->regs + CEC_TX_DATA_BASE + i);
214
215         /* Start transmission, configure hardware to add start and stop bits
216          * Signal free time is handled by the hardware
217          */
218         writel(CEC_TX_AUTO_SOM_EN | CEC_TX_AUTO_EOM_EN | CEC_TX_START |
219                msg->len, cec->regs + CEC_TX_ARRAY_CTRL);
220
221         return 0;
222 }
223
224 static void stih_tx_done(struct stih_cec *cec, u32 status)
225 {
226         if (status & CEC_TX_ERROR) {
227                 cec_transmit_done(cec->adap, CEC_TX_STATUS_ERROR, 0, 0, 0, 1);
228                 return;
229         }
230
231         if (status & CEC_TX_ARB_ERROR) {
232                 cec_transmit_done(cec->adap,
233                                   CEC_TX_STATUS_ARB_LOST, 1, 0, 0, 0);
234                 return;
235         }
236
237         if (!(status & CEC_TX_ACK_GET_STS)) {
238                 cec_transmit_done(cec->adap, CEC_TX_STATUS_NACK, 0, 1, 0, 0);
239                 return;
240         }
241
242         cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0);
243 }
244
245 static void stih_rx_done(struct stih_cec *cec, u32 status)
246 {
247         struct cec_msg msg = {};
248         u8 i;
249
250         if (status & CEC_RX_ERROR_MIN)
251                 return;
252
253         if (status & CEC_RX_ERROR_MAX)
254                 return;
255
256         msg.len = readl(cec->regs + CEC_DATA_ARRAY_STATUS) & 0x1f;
257
258         if (!msg.len)
259                 return;
260
261         if (msg.len > 16)
262                 msg.len = 16;
263
264         for (i = 0; i < msg.len; i++)
265                 msg.msg[i] = readl(cec->regs + CEC_RX_DATA_BASE + i);
266
267         cec_received_msg(cec->adap, &msg);
268 }
269
270 static irqreturn_t stih_cec_irq_handler_thread(int irq, void *priv)
271 {
272         struct stih_cec *cec = priv;
273
274         if (cec->irq_status & CEC_TX_DONE_STS)
275                 stih_tx_done(cec, cec->irq_status);
276
277         if (cec->irq_status & CEC_RX_DONE_STS)
278                 stih_rx_done(cec, cec->irq_status);
279
280         cec->irq_status = 0;
281
282         return IRQ_HANDLED;
283 }
284
285 static irqreturn_t stih_cec_irq_handler(int irq, void *priv)
286 {
287         struct stih_cec *cec = priv;
288
289         cec->irq_status = readl(cec->regs + CEC_STATUS);
290         writel(cec->irq_status, cec->regs + CEC_STATUS);
291
292         return IRQ_WAKE_THREAD;
293 }
294
295 static const struct cec_adap_ops sti_cec_adap_ops = {
296         .adap_enable = stih_cec_adap_enable,
297         .adap_log_addr = stih_cec_adap_log_addr,
298         .adap_transmit = stih_cec_adap_transmit,
299 };
300
301 static int stih_cec_probe(struct platform_device *pdev)
302 {
303         struct device *dev = &pdev->dev;
304         struct resource *res;
305         struct stih_cec *cec;
306         int ret;
307
308         cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
309         if (!cec)
310                 return -ENOMEM;
311
312         cec->dev = dev;
313
314         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
315         cec->regs = devm_ioremap_resource(dev, res);
316         if (IS_ERR(cec->regs))
317                 return PTR_ERR(cec->regs);
318
319         cec->irq = platform_get_irq(pdev, 0);
320         if (cec->irq < 0)
321                 return cec->irq;
322
323         ret = devm_request_threaded_irq(dev, cec->irq, stih_cec_irq_handler,
324                                         stih_cec_irq_handler_thread, 0,
325                                         pdev->name, cec);
326         if (ret)
327                 return ret;
328
329         cec->clk = devm_clk_get(dev, "cec-clk");
330         if (IS_ERR(cec->clk)) {
331                 dev_err(dev, "Cannot get cec clock\n");
332                 return PTR_ERR(cec->clk);
333         }
334
335         cec->adap = cec_allocate_adapter(&sti_cec_adap_ops, cec,
336                         CEC_NAME,
337                         CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH |
338                         CEC_CAP_PHYS_ADDR | CEC_CAP_TRANSMIT, 1);
339         ret = PTR_ERR_OR_ZERO(cec->adap);
340         if (ret)
341                 return ret;
342
343         ret = cec_register_adapter(cec->adap, &pdev->dev);
344         if (ret) {
345                 cec_delete_adapter(cec->adap);
346                 return ret;
347         }
348
349         platform_set_drvdata(pdev, cec);
350         return 0;
351 }
352
353 static int stih_cec_remove(struct platform_device *pdev)
354 {
355         return 0;
356 }
357
358 static const struct of_device_id stih_cec_match[] = {
359         {
360                 .compatible     = "st,stih-cec",
361         },
362         {},
363 };
364 MODULE_DEVICE_TABLE(of, stih_cec_match);
365
366 static struct platform_driver stih_cec_pdrv = {
367         .probe  = stih_cec_probe,
368         .remove = stih_cec_remove,
369         .driver = {
370                 .name           = CEC_NAME,
371                 .of_match_table = stih_cec_match,
372         },
373 };
374
375 module_platform_driver(stih_cec_pdrv);
376
377 MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@linaro.org>");
378 MODULE_LICENSE("GPL");
379 MODULE_DESCRIPTION("STIH4xx CEC driver");