1 // SPDX-License-Identifier: GPL-2.0
3 * ddbridge-mci.c: Digital Devices microcode interface
5 * Copyright (C) 2017-2018 Digital Devices GmbH
6 * Ralph Metzler <rjkm@metzlerbros.de>
7 * Marcus Metzler <mocm@metzlerbros.de>
11 #include "ddbridge-io.h"
12 #include "ddbridge-mci.h"
14 static LIST_HEAD(mci_list
);
16 static int mci_reset(struct mci
*state
)
18 struct ddb_link
*link
= state
->base
->link
;
22 ddblwritel(link
, MCI_CONTROL_RESET
, MCI_CONTROL
);
23 ddblwritel(link
, 0, MCI_CONTROL
+ 4); /* 1= no internal init */
25 ddblwritel(link
, 0, MCI_CONTROL
);
28 status
= ddblreadl(link
, MCI_CONTROL
);
29 if ((status
& MCI_CONTROL_READY
) == MCI_CONTROL_READY
)
35 if ((status
& MCI_CONTROL_READY
) == 0)
37 if (link
->ids
.device
== 0x0009)
38 ddblwritel(link
, SX8_TSCONFIG_MODE_NORMAL
, SX8_TSCONFIG
);
42 int ddb_mci_config(struct mci
*state
, u32 config
)
44 struct ddb_link
*link
= state
->base
->link
;
46 if (link
->ids
.device
!= 0x0009)
48 ddblwritel(link
, config
, SX8_TSCONFIG
);
52 static int _mci_cmd_unlocked(struct mci
*state
,
53 u32
*cmd
, u32 cmd_len
,
54 u32
*res
, u32 res_len
)
56 struct ddb_link
*link
= state
->base
->link
;
60 val
= ddblreadl(link
, MCI_CONTROL
);
61 if (val
& (MCI_CONTROL_RESET
| MCI_CONTROL_START_COMMAND
))
64 for (i
= 0; i
< cmd_len
; i
++)
65 ddblwritel(link
, cmd
[i
], MCI_COMMAND
+ i
* 4);
66 val
|= (MCI_CONTROL_START_COMMAND
| MCI_CONTROL_ENABLE_DONE_INTERRUPT
);
67 ddblwritel(link
, val
, MCI_CONTROL
);
69 stat
= wait_for_completion_timeout(&state
->base
->completion
, HZ
);
71 dev_warn(state
->base
->dev
, "MCI-%d: MCI timeout\n", state
->nr
);
75 for (i
= 0; i
< res_len
; i
++)
76 res
[i
] = ddblreadl(link
, MCI_RESULT
+ i
* 4);
80 int ddb_mci_cmd(struct mci
*state
,
81 struct mci_command
*command
,
82 struct mci_result
*result
)
86 mutex_lock(&state
->base
->mci_lock
);
87 stat
= _mci_cmd_unlocked(state
,
88 (u32
*)command
, sizeof(*command
) / sizeof(u32
),
89 (u32
*)result
, sizeof(*result
) / sizeof(u32
));
90 mutex_unlock(&state
->base
->mci_lock
);
94 static void mci_handler(void *priv
)
96 struct mci_base
*base
= (struct mci_base
*)priv
;
98 complete(&base
->completion
);
101 static struct mci_base
*match_base(void *key
)
105 list_for_each_entry(p
, &mci_list
, mci_list
)
111 static int probe(struct mci
*state
)
118 *ddb_mci_attach(struct ddb_input
*input
, struct mci_cfg
*cfg
, int nr
,
119 int (**fn_set_input
)(struct dvb_frontend
*fe
, int input
))
121 struct ddb_port
*port
= input
->port
;
122 struct ddb
*dev
= port
->dev
;
123 struct ddb_link
*link
= &dev
->link
[port
->lnr
];
124 struct mci_base
*base
;
126 void *key
= cfg
->type
? (void *)port
: (void *)link
;
128 state
= kzalloc(cfg
->state_size
, GFP_KERNEL
);
132 base
= match_base(key
);
137 base
= kzalloc(cfg
->base_size
, GFP_KERNEL
);
143 base
->dev
= dev
->dev
;
144 mutex_init(&base
->mci_lock
);
145 mutex_init(&base
->tuner_lock
);
146 ddb_irq_set(dev
, link
->nr
, 0, mci_handler
, base
);
147 init_completion(&base
->completion
);
149 if (probe(state
) < 0) {
153 list_add(&base
->mci_list
, &mci_list
);
155 cfg
->base_init(base
);
157 memcpy(&state
->fe
.ops
, cfg
->fe_ops
, sizeof(struct dvb_frontend_ops
));
158 state
->fe
.demodulator_priv
= state
;
160 *fn_set_input
= cfg
->set_input
;