1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * ddbridge-mci.c: Digital Devices microcode interface 4 * 5 * Copyright (C) 2017-2018 Digital Devices GmbH 6 * Ralph Metzler <rjkm@metzlerbros.de> 7 * Marcus Metzler <mocm@metzlerbros.de> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * version 2 only, as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19 #include "ddbridge.h" 20 #include "ddbridge-io.h" 21 #include "ddbridge-mci.h" 22 23 static LIST_HEAD(mci_list); 24 25 static int mci_reset(struct mci *state) 26 { 27 struct ddb_link *link = state->base->link; 28 u32 status = 0; 29 u32 timeout = 40; 30 31 ddblwritel(link, MCI_CONTROL_RESET, MCI_CONTROL); 32 ddblwritel(link, 0, MCI_CONTROL + 4); /* 1= no internal init */ 33 msleep(300); 34 ddblwritel(link, 0, MCI_CONTROL); 35 36 while (1) { 37 status = ddblreadl(link, MCI_CONTROL); 38 if ((status & MCI_CONTROL_READY) == MCI_CONTROL_READY) 39 break; 40 if (--timeout == 0) 41 break; 42 msleep(50); 43 } 44 if ((status & MCI_CONTROL_READY) == 0) 45 return -1; 46 if (link->ids.device == 0x0009) 47 ddblwritel(link, SX8_TSCONFIG_MODE_NORMAL, SX8_TSCONFIG); 48 return 0; 49 } 50 51 int ddb_mci_config(struct mci *state, u32 config) 52 { 53 struct ddb_link *link = state->base->link; 54 55 if (link->ids.device != 0x0009) 56 return -EINVAL; 57 ddblwritel(link, config, SX8_TSCONFIG); 58 return 0; 59 } 60 61 static int _mci_cmd_unlocked(struct mci *state, 62 u32 *cmd, u32 cmd_len, 63 u32 *res, u32 res_len) 64 { 65 struct ddb_link *link = state->base->link; 66 u32 i, val; 67 unsigned long stat; 68 69 val = ddblreadl(link, MCI_CONTROL); 70 if (val & (MCI_CONTROL_RESET | MCI_CONTROL_START_COMMAND)) 71 return -EIO; 72 if (cmd && cmd_len) 73 for (i = 0; i < cmd_len; i++) 74 ddblwritel(link, cmd[i], MCI_COMMAND + i * 4); 75 val |= (MCI_CONTROL_START_COMMAND | MCI_CONTROL_ENABLE_DONE_INTERRUPT); 76 ddblwritel(link, val, MCI_CONTROL); 77 78 stat = wait_for_completion_timeout(&state->base->completion, HZ); 79 if (stat == 0) { 80 dev_warn(state->base->dev, "MCI-%d: MCI timeout\n", state->nr); 81 return -EIO; 82 } 83 if (res && res_len) 84 for (i = 0; i < res_len; i++) 85 res[i] = ddblreadl(link, MCI_RESULT + i * 4); 86 return 0; 87 } 88 89 int ddb_mci_cmd(struct mci *state, 90 struct mci_command *command, 91 struct mci_result *result) 92 { 93 int stat; 94 95 mutex_lock(&state->base->mci_lock); 96 stat = _mci_cmd_unlocked(state, 97 (u32 *)command, sizeof(*command) / sizeof(u32), 98 (u32 *)result, sizeof(*result) / sizeof(u32)); 99 mutex_unlock(&state->base->mci_lock); 100 return stat; 101 } 102 103 static void mci_handler(void *priv) 104 { 105 struct mci_base *base = (struct mci_base *)priv; 106 107 complete(&base->completion); 108 } 109 110 static struct mci_base *match_base(void *key) 111 { 112 struct mci_base *p; 113 114 list_for_each_entry(p, &mci_list, mci_list) 115 if (p->key == key) 116 return p; 117 return NULL; 118 } 119 120 static int probe(struct mci *state) 121 { 122 mci_reset(state); 123 return 0; 124 } 125 126 struct dvb_frontend 127 *ddb_mci_attach(struct ddb_input *input, struct mci_cfg *cfg, int nr, 128 int (**fn_set_input)(struct dvb_frontend *fe, int input)) 129 { 130 struct ddb_port *port = input->port; 131 struct ddb *dev = port->dev; 132 struct ddb_link *link = &dev->link[port->lnr]; 133 struct mci_base *base; 134 struct mci *state; 135 void *key = cfg->type ? (void *)port : (void *)link; 136 137 state = kzalloc(cfg->state_size, GFP_KERNEL); 138 if (!state) 139 return NULL; 140 141 base = match_base(key); 142 if (base) { 143 base->count++; 144 state->base = base; 145 } else { 146 base = kzalloc(cfg->base_size, GFP_KERNEL); 147 if (!base) 148 goto fail; 149 base->key = key; 150 base->count = 1; 151 base->link = link; 152 base->dev = dev->dev; 153 mutex_init(&base->mci_lock); 154 mutex_init(&base->tuner_lock); 155 ddb_irq_set(dev, link->nr, 0, mci_handler, base); 156 init_completion(&base->completion); 157 state->base = base; 158 if (probe(state) < 0) { 159 kfree(base); 160 goto fail; 161 } 162 list_add(&base->mci_list, &mci_list); 163 if (cfg->base_init) 164 cfg->base_init(base); 165 } 166 memcpy(&state->fe.ops, cfg->fe_ops, sizeof(struct dvb_frontend_ops)); 167 state->fe.demodulator_priv = state; 168 state->nr = nr; 169 *fn_set_input = cfg->set_input; 170 state->tuner = nr; 171 state->demod = nr; 172 if (cfg->init) 173 cfg->init(state); 174 return &state->fe; 175 fail: 176 kfree(state); 177 return NULL; 178 } 179