Googler | 06419a4 | 2022-05-17 21:32:34 +0800 | [diff] [blame^] | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
Googler | e00b8eb | 2019-07-08 16:37:07 -0700 | [diff] [blame] | 2 | /* |
Googler | 06419a4 | 2022-05-17 21:32:34 +0800 | [diff] [blame^] | 3 | * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
Googler | e00b8eb | 2019-07-08 16:37:07 -0700 | [diff] [blame] | 4 | */ |
| 5 | |
| 6 | #include <linux/io.h> |
| 7 | #include "pinctrl-meson.h" |
| 8 | #include "pinconf-meson-g12a.h" |
| 9 | |
| 10 | static 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 | |
| 27 | static 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 | |
| 37 | int 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 | |
Googler | 06419a4 | 2022-05-17 21:32:34 +0800 | [diff] [blame^] | 50 | if (arg < 1 || arg > 4) { |
| 51 | debug("pin %u: invalid drive-strength [1-4]: %d\n", pin, arg); |
Googler | e00b8eb | 2019-07-08 16:37:07 -0700 | [diff] [blame] | 52 | return -EINVAL; |
| 53 | } |
Googler | 06419a4 | 2022-05-17 21:32:34 +0800 | [diff] [blame^] | 54 | |
| 55 | arg = arg - 1; |
| 56 | |
Googler | e00b8eb | 2019-07-08 16:37:07 -0700 | [diff] [blame] | 57 | meson_drive_calc_reg_and_bit(drive_bank, pin, ®, &bit); |
| 58 | |
| 59 | clrsetbits_le32(priv->reg_drive + reg, 0x3 << bit, (arg & 0x3) << bit); |
| 60 | |
| 61 | return 0; |
| 62 | } |