9
9
#include <linux/errno.h>
10
10
#include <linux/interrupt.h>
11
11
#include <linux/io.h>
12
+ #include <linux/irq.h>
12
13
#include <linux/mfd/syscon.h>
13
14
#include <linux/module.h>
14
15
#include <linux/of.h>
28
29
29
30
#define KCS_CHANNEL_MAX 4
30
31
32
+ /*
33
+ * Field class descriptions
34
+ *
35
+ * LPCyE Enable LPC channel y
36
+ * IBFIEy Input Buffer Full IRQ Enable for LPC channel y
37
+ * IRQxEy Assert SerIRQ x for LPC channel y (Deprecated, use IDyIRQX, IRQXEy)
38
+ * IDyIRQX Use the specified 4-bit SerIRQ for LPC channel y
39
+ * SELyIRQX SerIRQ polarity for LPC channel y (low: 0, high: 1)
40
+ * IRQXEy Assert the SerIRQ specified in IDyIRQX for LPC channel y
41
+ */
42
+
43
+ #define LPC_TYIRQX_LOW 0b00
44
+ #define LPC_TYIRQX_HIGH 0b01
45
+ #define LPC_TYIRQX_RSVD 0b10
46
+ #define LPC_TYIRQX_RISING 0b11
47
+
31
48
#define LPC_HICR0 0x000
32
49
#define LPC_HICR0_LPC3E BIT(7)
33
50
#define LPC_HICR0_LPC2E BIT(6)
39
56
#define LPC_HICR4 0x010
40
57
#define LPC_HICR4_LADR12AS BIT(7)
41
58
#define LPC_HICR4_KCSENBL BIT(2)
59
+ #define LPC_SIRQCR0 0x070
60
+ /* IRQ{12,1}E1 are deprecated as of AST2600 A3 but necessary for prior chips */
61
+ #define LPC_SIRQCR0_IRQ12E1 BIT(1)
62
+ #define LPC_SIRQCR0_IRQ1E1 BIT(0)
63
+ #define LPC_HICR5 0x080
64
+ #define LPC_HICR5_ID3IRQX_MASK GENMASK(23, 20)
65
+ #define LPC_HICR5_ID3IRQX_SHIFT 20
66
+ #define LPC_HICR5_ID2IRQX_MASK GENMASK(19, 16)
67
+ #define LPC_HICR5_ID2IRQX_SHIFT 16
68
+ #define LPC_HICR5_SEL3IRQX BIT(15)
69
+ #define LPC_HICR5_IRQXE3 BIT(14)
70
+ #define LPC_HICR5_SEL2IRQX BIT(13)
71
+ #define LPC_HICR5_IRQXE2 BIT(12)
42
72
#define LPC_LADR3H 0x014
43
73
#define LPC_LADR3L 0x018
44
74
#define LPC_LADR12H 0x01C
55
85
#define LPC_HICRB 0x100
56
86
#define LPC_HICRB_IBFIF4 BIT(1)
57
87
#define LPC_HICRB_LPC4E BIT(0)
88
+ #define LPC_HICRC 0x104
89
+ #define LPC_HICRC_ID4IRQX_MASK GENMASK(7, 4)
90
+ #define LPC_HICRC_ID4IRQX_SHIFT 4
91
+ #define LPC_HICRC_TY4IRQX_MASK GENMASK(3, 2)
92
+ #define LPC_HICRC_TY4IRQX_SHIFT 2
93
+ #define LPC_HICRC_OBF4_AUTO_CLR BIT(1)
94
+ #define LPC_HICRC_IRQXE4 BIT(0)
58
95
#define LPC_LADR4 0x110
59
96
#define LPC_IDR4 0x114
60
97
#define LPC_ODR4 0x118
61
98
#define LPC_STR4 0x11C
62
99
63
100
#define OBE_POLL_PERIOD (HZ / 2)
64
101
102
+ enum aspeed_kcs_irq_mode {
103
+ aspeed_kcs_irq_none ,
104
+ aspeed_kcs_irq_serirq ,
105
+ };
106
+
65
107
struct aspeed_kcs_bmc {
66
108
struct kcs_bmc_device kcs_bmc ;
67
109
68
110
struct regmap * map ;
69
111
112
+ struct {
113
+ enum aspeed_kcs_irq_mode mode ;
114
+ int id ;
115
+ } upstream_irq ;
116
+
70
117
struct {
71
118
spinlock_t lock ;
72
119
bool remove ;
@@ -103,6 +150,49 @@ static void aspeed_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data)
103
150
104
151
rc = regmap_write (priv -> map , reg , data );
105
152
WARN (rc != 0 , "regmap_write() failed: %d\n" , rc );
153
+
154
+ /* Trigger the upstream IRQ on ODR writes, if enabled */
155
+
156
+ switch (reg ) {
157
+ case LPC_ODR1 :
158
+ case LPC_ODR2 :
159
+ case LPC_ODR3 :
160
+ case LPC_ODR4 :
161
+ break ;
162
+ default :
163
+ return ;
164
+ }
165
+
166
+ if (priv -> upstream_irq .mode != aspeed_kcs_irq_serirq )
167
+ return ;
168
+
169
+ switch (kcs_bmc -> channel ) {
170
+ case 1 :
171
+ switch (priv -> upstream_irq .id ) {
172
+ case 12 :
173
+ regmap_update_bits (priv -> map , LPC_SIRQCR0 , LPC_SIRQCR0_IRQ12E1 ,
174
+ LPC_SIRQCR0_IRQ12E1 );
175
+ break ;
176
+ case 1 :
177
+ regmap_update_bits (priv -> map , LPC_SIRQCR0 , LPC_SIRQCR0_IRQ1E1 ,
178
+ LPC_SIRQCR0_IRQ1E1 );
179
+ break ;
180
+ default :
181
+ break ;
182
+ }
183
+ break ;
184
+ case 2 :
185
+ regmap_update_bits (priv -> map , LPC_HICR5 , LPC_HICR5_IRQXE2 , LPC_HICR5_IRQXE2 );
186
+ break ;
187
+ case 3 :
188
+ regmap_update_bits (priv -> map , LPC_HICR5 , LPC_HICR5_IRQXE3 , LPC_HICR5_IRQXE3 );
189
+ break ;
190
+ case 4 :
191
+ regmap_update_bits (priv -> map , LPC_HICRC , LPC_HICRC_IRQXE4 , LPC_HICRC_IRQXE4 );
192
+ break ;
193
+ default :
194
+ break ;
195
+ }
106
196
}
107
197
108
198
static void aspeed_kcs_updateb (struct kcs_bmc_device * kcs_bmc , u32 reg , u8 mask , u8 val )
@@ -161,6 +251,73 @@ static void aspeed_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr)
161
251
}
162
252
}
163
253
254
+ static inline int aspeed_kcs_map_serirq_type (u32 dt_type )
255
+ {
256
+ switch (dt_type ) {
257
+ case IRQ_TYPE_EDGE_RISING :
258
+ return LPC_TYIRQX_RISING ;
259
+ case IRQ_TYPE_LEVEL_HIGH :
260
+ return LPC_TYIRQX_HIGH ;
261
+ case IRQ_TYPE_LEVEL_LOW :
262
+ return LPC_TYIRQX_LOW ;
263
+ default :
264
+ return - EINVAL ;
265
+ }
266
+ }
267
+
268
+ static int aspeed_kcs_config_upstream_irq (struct aspeed_kcs_bmc * priv , u32 id , u32 dt_type )
269
+ {
270
+ unsigned int mask , val , hw_type ;
271
+
272
+ if (id > 15 )
273
+ return - EINVAL ;
274
+
275
+ hw_type = aspeed_kcs_map_serirq_type (dt_type );
276
+ if (hw_type < 0 )
277
+ return hw_type ;
278
+
279
+ priv -> upstream_irq .mode = aspeed_kcs_irq_serirq ;
280
+ priv -> upstream_irq .id = id ;
281
+
282
+ switch (priv -> kcs_bmc .channel ) {
283
+ case 1 :
284
+ /* Needs IRQxE1 rather than (ID1IRQX, SEL1IRQX, IRQXE1) before AST2600 A3 */
285
+ break ;
286
+ case 2 :
287
+ if (!(hw_type == LPC_TYIRQX_LOW || hw_type == LPC_TYIRQX_HIGH ))
288
+ return - EINVAL ;
289
+
290
+ mask = LPC_HICR5_SEL2IRQX | LPC_HICR5_ID2IRQX_MASK ;
291
+ val = (id << LPC_HICR5_ID2IRQX_SHIFT );
292
+ val |= (hw_type == LPC_TYIRQX_HIGH ) ? LPC_HICR5_SEL2IRQX : 0 ;
293
+ regmap_update_bits (priv -> map , LPC_HICR5 , mask , val );
294
+
295
+ break ;
296
+ case 3 :
297
+ if (!(hw_type == LPC_TYIRQX_LOW || hw_type == LPC_TYIRQX_HIGH ))
298
+ return - EINVAL ;
299
+
300
+ mask = LPC_HICR5_SEL3IRQX | LPC_HICR5_ID3IRQX_MASK ;
301
+ val = (id << LPC_HICR5_ID3IRQX_SHIFT );
302
+ val |= (hw_type == LPC_TYIRQX_HIGH ) ? LPC_HICR5_SEL3IRQX : 0 ;
303
+ regmap_update_bits (priv -> map , LPC_HICR5 , mask , val );
304
+
305
+ break ;
306
+ case 4 :
307
+ mask = LPC_HICRC_ID4IRQX_MASK | LPC_HICRC_TY4IRQX_MASK | LPC_HICRC_OBF4_AUTO_CLR ;
308
+ val = (id << LPC_HICRC_ID4IRQX_SHIFT ) | (hw_type << LPC_HICRC_TY4IRQX_SHIFT );
309
+ regmap_update_bits (priv -> map , LPC_HICRC , mask , val );
310
+ break ;
311
+ default :
312
+ dev_warn (priv -> kcs_bmc .dev ,
313
+ "SerIRQ configuration not supported on KCS channel %d\n" ,
314
+ priv -> kcs_bmc .channel );
315
+ return - EINVAL ;
316
+ }
317
+
318
+ return 0 ;
319
+ }
320
+
164
321
static void aspeed_kcs_enable_channel (struct kcs_bmc_device * kcs_bmc , bool enable )
165
322
{
166
323
struct aspeed_kcs_bmc * priv = to_aspeed_kcs_bmc (kcs_bmc );
@@ -262,7 +419,7 @@ static irqreturn_t aspeed_kcs_irq(int irq, void *arg)
262
419
return kcs_bmc_handle_event (kcs_bmc );
263
420
}
264
421
265
- static int aspeed_kcs_config_irq (struct kcs_bmc_device * kcs_bmc ,
422
+ static int aspeed_kcs_config_downstream_irq (struct kcs_bmc_device * kcs_bmc ,
266
423
struct platform_device * pdev )
267
424
{
268
425
struct device * dev = & pdev -> dev ;
@@ -368,6 +525,8 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
368
525
struct aspeed_kcs_bmc * priv ;
369
526
struct device_node * np ;
370
527
int rc , channel , addr ;
528
+ bool have_upstream_irq ;
529
+ u32 upstream_irq [2 ];
371
530
372
531
np = pdev -> dev .of_node -> parent ;
373
532
if (!of_device_is_compatible (np , "aspeed,ast2400-lpc-v2" ) &&
@@ -376,6 +535,7 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
376
535
dev_err (& pdev -> dev , "unsupported LPC device binding\n" );
377
536
return - ENODEV ;
378
537
}
538
+
379
539
ops = of_device_get_match_data (& pdev -> dev );
380
540
if (!ops )
381
541
return - EINVAL ;
@@ -388,6 +548,13 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
388
548
if (addr < 0 )
389
549
return addr ;
390
550
551
+ np = pdev -> dev .of_node ;
552
+ rc = of_property_read_u32_array (np , "aspeed,lpc-interrupts" , upstream_irq , 2 );
553
+ if (rc && rc != - EINVAL )
554
+ return - EINVAL ;
555
+
556
+ have_upstream_irq = !rc ;
557
+
391
558
priv = devm_kzalloc (& pdev -> dev , sizeof (* priv ), GFP_KERNEL );
392
559
if (!priv )
393
560
return - ENOMEM ;
@@ -410,10 +577,20 @@ static int aspeed_kcs_probe(struct platform_device *pdev)
410
577
411
578
aspeed_kcs_set_address (kcs_bmc , addr );
412
579
413
- rc = aspeed_kcs_config_irq (kcs_bmc , pdev );
580
+ /* Host to BMC IRQ */
581
+ rc = aspeed_kcs_config_downstream_irq (kcs_bmc , pdev );
414
582
if (rc )
415
583
return rc ;
416
584
585
+ /* BMC to Host IRQ */
586
+ if (have_upstream_irq ) {
587
+ rc = aspeed_kcs_config_upstream_irq (priv , upstream_irq [0 ], upstream_irq [1 ]);
588
+ if (rc < 0 )
589
+ return rc ;
590
+ } else {
591
+ priv -> upstream_irq .mode = aspeed_kcs_irq_none ;
592
+ }
593
+
417
594
platform_set_drvdata (pdev , priv );
418
595
419
596
aspeed_kcs_irq_mask_update (kcs_bmc , (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE ), 0 );
@@ -480,4 +657,5 @@ module_platform_driver(ast_kcs_bmc_driver);
480
657
481
658
MODULE_LICENSE ("GPL v2" );
482
659
MODULE_AUTHOR (
"Haiyue Wang <[email protected] >" );
660
+ MODULE_AUTHOR (
"Andrew Jeffery <[email protected] >" );
483
661
MODULE_DESCRIPTION ("Aspeed device interface to the KCS BMC device" );
0 commit comments