0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/counter.h>
0009 #include <linux/mfd/syscon.h>
0010 #include <linux/module.h>
0011 #include <linux/mutex.h>
0012 #include <linux/of.h>
0013 #include <linux/of_device.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regmap.h>
0016 #include <soc/at91/atmel_tcb.h>
0017
0018 #define ATMEL_TC_CMR_MASK (ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \
0019 ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \
0020 ATMEL_TC_LDBSTOP)
0021
0022 #define ATMEL_TC_QDEN BIT(8)
0023 #define ATMEL_TC_POSEN BIT(9)
0024
0025 struct mchp_tc_data {
0026 const struct atmel_tcb_config *tc_cfg;
0027 struct regmap *regmap;
0028 int qdec_mode;
0029 int num_channels;
0030 int channel[2];
0031 bool trig_inverted;
0032 };
0033
0034 static const enum counter_function mchp_tc_count_functions[] = {
0035 COUNTER_FUNCTION_INCREASE,
0036 COUNTER_FUNCTION_QUADRATURE_X4,
0037 };
0038
0039 static const enum counter_synapse_action mchp_tc_synapse_actions[] = {
0040 COUNTER_SYNAPSE_ACTION_NONE,
0041 COUNTER_SYNAPSE_ACTION_RISING_EDGE,
0042 COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
0043 COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
0044 };
0045
0046 static struct counter_signal mchp_tc_count_signals[] = {
0047 {
0048 .id = 0,
0049 .name = "Channel A",
0050 },
0051 {
0052 .id = 1,
0053 .name = "Channel B",
0054 }
0055 };
0056
0057 static struct counter_synapse mchp_tc_count_synapses[] = {
0058 {
0059 .actions_list = mchp_tc_synapse_actions,
0060 .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
0061 .signal = &mchp_tc_count_signals[0]
0062 },
0063 {
0064 .actions_list = mchp_tc_synapse_actions,
0065 .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
0066 .signal = &mchp_tc_count_signals[1]
0067 }
0068 };
0069
0070 static int mchp_tc_count_function_read(struct counter_device *counter,
0071 struct counter_count *count,
0072 enum counter_function *function)
0073 {
0074 struct mchp_tc_data *const priv = counter_priv(counter);
0075
0076 if (priv->qdec_mode)
0077 *function = COUNTER_FUNCTION_QUADRATURE_X4;
0078 else
0079 *function = COUNTER_FUNCTION_INCREASE;
0080
0081 return 0;
0082 }
0083
0084 static int mchp_tc_count_function_write(struct counter_device *counter,
0085 struct counter_count *count,
0086 enum counter_function function)
0087 {
0088 struct mchp_tc_data *const priv = counter_priv(counter);
0089 u32 bmr, cmr;
0090
0091 regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr);
0092 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
0093
0094
0095 cmr &= ~ATMEL_TC_WAVE;
0096
0097 switch (function) {
0098 case COUNTER_FUNCTION_INCREASE:
0099 priv->qdec_mode = 0;
0100
0101 bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN);
0102 if (priv->tc_cfg->has_gclk)
0103 cmr |= ATMEL_TC_TIMER_CLOCK2;
0104 else
0105 cmr |= ATMEL_TC_TIMER_CLOCK1;
0106
0107 cmr |= ATMEL_TC_CMR_MASK;
0108 cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0);
0109 break;
0110 case COUNTER_FUNCTION_QUADRATURE_X4:
0111 if (!priv->tc_cfg->has_qdec)
0112 return -EINVAL;
0113
0114 if (priv->num_channels < 2 || priv->channel[0] != 0 ||
0115 priv->channel[1] != 1) {
0116 pr_err("Invalid channels number or id for quadrature mode\n");
0117 return -EINVAL;
0118 }
0119 priv->qdec_mode = 1;
0120 bmr |= ATMEL_TC_QDEN | ATMEL_TC_POSEN;
0121 cmr |= ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_ABETRG | ATMEL_TC_XC0;
0122 break;
0123 default:
0124
0125 return -EINVAL;
0126 }
0127
0128 regmap_write(priv->regmap, ATMEL_TC_BMR, bmr);
0129 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), cmr);
0130
0131
0132 regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CCR),
0133 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
0134
0135 if (priv->qdec_mode) {
0136 regmap_write(priv->regmap,
0137 ATMEL_TC_REG(priv->channel[1], CMR), cmr);
0138 regmap_write(priv->regmap,
0139 ATMEL_TC_REG(priv->channel[1], CCR),
0140 ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
0141 }
0142
0143 return 0;
0144 }
0145
0146 static int mchp_tc_count_signal_read(struct counter_device *counter,
0147 struct counter_signal *signal,
0148 enum counter_signal_level *lvl)
0149 {
0150 struct mchp_tc_data *const priv = counter_priv(counter);
0151 bool sigstatus;
0152 u32 sr;
0153
0154 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
0155
0156 if (priv->trig_inverted)
0157 sigstatus = (sr & ATMEL_TC_MTIOB);
0158 else
0159 sigstatus = (sr & ATMEL_TC_MTIOA);
0160
0161 *lvl = sigstatus ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW;
0162
0163 return 0;
0164 }
0165
0166 static int mchp_tc_count_action_read(struct counter_device *counter,
0167 struct counter_count *count,
0168 struct counter_synapse *synapse,
0169 enum counter_synapse_action *action)
0170 {
0171 struct mchp_tc_data *const priv = counter_priv(counter);
0172 u32 cmr;
0173
0174 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
0175
0176 switch (cmr & ATMEL_TC_ETRGEDG) {
0177 default:
0178 *action = COUNTER_SYNAPSE_ACTION_NONE;
0179 break;
0180 case ATMEL_TC_ETRGEDG_RISING:
0181 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE;
0182 break;
0183 case ATMEL_TC_ETRGEDG_FALLING:
0184 *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE;
0185 break;
0186 case ATMEL_TC_ETRGEDG_BOTH:
0187 *action = COUNTER_SYNAPSE_ACTION_BOTH_EDGES;
0188 break;
0189 }
0190
0191 return 0;
0192 }
0193
0194 static int mchp_tc_count_action_write(struct counter_device *counter,
0195 struct counter_count *count,
0196 struct counter_synapse *synapse,
0197 enum counter_synapse_action action)
0198 {
0199 struct mchp_tc_data *const priv = counter_priv(counter);
0200 u32 edge = ATMEL_TC_ETRGEDG_NONE;
0201
0202
0203 if (priv->qdec_mode)
0204 return -EINVAL;
0205
0206 switch (action) {
0207 case COUNTER_SYNAPSE_ACTION_NONE:
0208 edge = ATMEL_TC_ETRGEDG_NONE;
0209 break;
0210 case COUNTER_SYNAPSE_ACTION_RISING_EDGE:
0211 edge = ATMEL_TC_ETRGEDG_RISING;
0212 break;
0213 case COUNTER_SYNAPSE_ACTION_FALLING_EDGE:
0214 edge = ATMEL_TC_ETRGEDG_FALLING;
0215 break;
0216 case COUNTER_SYNAPSE_ACTION_BOTH_EDGES:
0217 edge = ATMEL_TC_ETRGEDG_BOTH;
0218 break;
0219 default:
0220
0221 return -EINVAL;
0222 }
0223
0224 return regmap_write_bits(priv->regmap,
0225 ATMEL_TC_REG(priv->channel[0], CMR),
0226 ATMEL_TC_ETRGEDG, edge);
0227 }
0228
0229 static int mchp_tc_count_read(struct counter_device *counter,
0230 struct counter_count *count, u64 *val)
0231 {
0232 struct mchp_tc_data *const priv = counter_priv(counter);
0233 u32 cnt;
0234
0235 regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CV), &cnt);
0236 *val = cnt;
0237
0238 return 0;
0239 }
0240
0241 static struct counter_count mchp_tc_counts[] = {
0242 {
0243 .id = 0,
0244 .name = "Timer Counter",
0245 .functions_list = mchp_tc_count_functions,
0246 .num_functions = ARRAY_SIZE(mchp_tc_count_functions),
0247 .synapses = mchp_tc_count_synapses,
0248 .num_synapses = ARRAY_SIZE(mchp_tc_count_synapses),
0249 },
0250 };
0251
0252 static const struct counter_ops mchp_tc_ops = {
0253 .signal_read = mchp_tc_count_signal_read,
0254 .count_read = mchp_tc_count_read,
0255 .function_read = mchp_tc_count_function_read,
0256 .function_write = mchp_tc_count_function_write,
0257 .action_read = mchp_tc_count_action_read,
0258 .action_write = mchp_tc_count_action_write
0259 };
0260
0261 static const struct atmel_tcb_config tcb_rm9200_config = {
0262 .counter_width = 16,
0263 };
0264
0265 static const struct atmel_tcb_config tcb_sam9x5_config = {
0266 .counter_width = 32,
0267 };
0268
0269 static const struct atmel_tcb_config tcb_sama5d2_config = {
0270 .counter_width = 32,
0271 .has_gclk = true,
0272 .has_qdec = true,
0273 };
0274
0275 static const struct atmel_tcb_config tcb_sama5d3_config = {
0276 .counter_width = 32,
0277 .has_qdec = true,
0278 };
0279
0280 static const struct of_device_id atmel_tc_of_match[] = {
0281 { .compatible = "atmel,at91rm9200-tcb", .data = &tcb_rm9200_config, },
0282 { .compatible = "atmel,at91sam9x5-tcb", .data = &tcb_sam9x5_config, },
0283 { .compatible = "atmel,sama5d2-tcb", .data = &tcb_sama5d2_config, },
0284 { .compatible = "atmel,sama5d3-tcb", .data = &tcb_sama5d3_config, },
0285 { }
0286 };
0287
0288 static void mchp_tc_clk_remove(void *ptr)
0289 {
0290 clk_disable_unprepare((struct clk *)ptr);
0291 }
0292
0293 static int mchp_tc_probe(struct platform_device *pdev)
0294 {
0295 struct device_node *np = pdev->dev.of_node;
0296 const struct atmel_tcb_config *tcb_config;
0297 const struct of_device_id *match;
0298 struct counter_device *counter;
0299 struct mchp_tc_data *priv;
0300 char clk_name[7];
0301 struct regmap *regmap;
0302 struct clk *clk[3];
0303 int channel;
0304 int ret, i;
0305
0306 counter = devm_counter_alloc(&pdev->dev, sizeof(*priv));
0307 if (!counter)
0308 return -ENOMEM;
0309 priv = counter_priv(counter);
0310
0311 match = of_match_node(atmel_tc_of_match, np->parent);
0312 tcb_config = match->data;
0313 if (!tcb_config) {
0314 dev_err(&pdev->dev, "No matching parent node found\n");
0315 return -ENODEV;
0316 }
0317
0318 regmap = syscon_node_to_regmap(np->parent);
0319 if (IS_ERR(regmap))
0320 return PTR_ERR(regmap);
0321
0322
0323 priv->num_channels = of_property_count_u32_elems(np, "reg");
0324 if (priv->num_channels < 0) {
0325 dev_err(&pdev->dev, "Invalid or missing channel\n");
0326 return -EINVAL;
0327 }
0328
0329
0330 for (i = 0; i < priv->num_channels; i++) {
0331 ret = of_property_read_u32_index(np, "reg", i, &channel);
0332 if (ret < 0 || channel > 2)
0333 return -ENODEV;
0334
0335 priv->channel[i] = channel;
0336
0337 snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
0338
0339 clk[i] = of_clk_get_by_name(np->parent, clk_name);
0340 if (IS_ERR(clk[i])) {
0341
0342 clk[i] = of_clk_get_by_name(np->parent, "t0_clk");
0343 if (IS_ERR(clk[i]))
0344 return PTR_ERR(clk[i]);
0345 }
0346
0347 ret = clk_prepare_enable(clk[i]);
0348 if (ret)
0349 return ret;
0350
0351 ret = devm_add_action_or_reset(&pdev->dev,
0352 mchp_tc_clk_remove,
0353 clk[i]);
0354 if (ret)
0355 return ret;
0356
0357 dev_dbg(&pdev->dev,
0358 "Initialized capture mode on channel %d\n",
0359 channel);
0360 }
0361
0362 priv->tc_cfg = tcb_config;
0363 priv->regmap = regmap;
0364 counter->name = dev_name(&pdev->dev);
0365 counter->parent = &pdev->dev;
0366 counter->ops = &mchp_tc_ops;
0367 counter->num_counts = ARRAY_SIZE(mchp_tc_counts);
0368 counter->counts = mchp_tc_counts;
0369 counter->num_signals = ARRAY_SIZE(mchp_tc_count_signals);
0370 counter->signals = mchp_tc_count_signals;
0371
0372 ret = devm_counter_add(&pdev->dev, counter);
0373 if (ret < 0)
0374 return dev_err_probe(&pdev->dev, ret, "Failed to add counter\n");
0375
0376 return 0;
0377 }
0378
0379 static const struct of_device_id mchp_tc_dt_ids[] = {
0380 { .compatible = "microchip,tcb-capture", },
0381 { },
0382 };
0383 MODULE_DEVICE_TABLE(of, mchp_tc_dt_ids);
0384
0385 static struct platform_driver mchp_tc_driver = {
0386 .probe = mchp_tc_probe,
0387 .driver = {
0388 .name = "microchip-tcb-capture",
0389 .of_match_table = mchp_tc_dt_ids,
0390 },
0391 };
0392 module_platform_driver(mchp_tc_driver);
0393
0394 MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>");
0395 MODULE_DESCRIPTION("Microchip TCB Capture driver");
0396 MODULE_LICENSE("GPL v2");