blob: f81124e6e1455ee138fdd730c8b17848eb8c060a [file] [log] [blame]
Googler06419a42022-05-17 21:32:34 +08001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
Googlere00b8eb2019-07-08 16:37:07 -07002/*
Googler06419a42022-05-17 21:32:34 +08003 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
Googlere00b8eb2019-07-08 16:37:07 -07004 */
5
6#include <linux/io.h>
7#include "pinctrl-meson.h"
8#include "pinconf-meson-g12a.h"
9
10static int meson_get_drive_bank(struct meson_pinctrl *priv, unsigned int pin,
11 struct meson_drive_bank **bank)
12{
13 int i;
14 struct meson_drive_data *drive = priv->data->drv_data;
15
16 for (i = 0; i < drive->num_drive_banks; i++) {
17 if (pin >= drive->drive_banks[i].first &&
18 pin <= drive->drive_banks[i].last) {
19 *bank = &drive->drive_banks[i];
20 return 0;
21 }
22 }
23
24 return -EINVAL;
25}
26
27static void meson_drive_calc_reg_and_bit(struct meson_drive_bank *drive_bank,
28 unsigned int pin, unsigned int *reg,
29 unsigned int *bit)
30{
31 int shift = pin - drive_bank->first;
32
33 *reg = (drive_bank->reg + (drive_bank->bit + (shift << 1)) / 32) * 4;
34 *bit = (drive_bank->bit + (shift << 1)) % 32;
35}
36
37int meson_pinconf_set_drive_strength(struct meson_pinctrl *priv,
38 unsigned int pin, u16 arg)
39{
40 struct meson_drive_bank *drive_bank;
41 unsigned int reg, bit;
42 int ret;
43
44 debug("pin %u: set drive-strength\n", pin);
45
46 ret = meson_get_drive_bank(priv, pin, &drive_bank);
47 if (ret)
48 return ret;
49
Googler06419a42022-05-17 21:32:34 +080050 if (arg < 1 || arg > 4) {
51 debug("pin %u: invalid drive-strength [1-4]: %d\n", pin, arg);
Googlere00b8eb2019-07-08 16:37:07 -070052 return -EINVAL;
53 }
Googler06419a42022-05-17 21:32:34 +080054
55 arg = arg - 1;
56
Googlere00b8eb2019-07-08 16:37:07 -070057 meson_drive_calc_reg_and_bit(drive_bank, pin, &reg, &bit);
58
59 clrsetbits_le32(priv->reg_drive + reg, 0x3 << bit, (arg & 0x3) << bit);
60
61 return 0;
62}