Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause
0002 /*
0003  * Copyright (c) 2020, MIPI Alliance, Inc.
0004  *
0005  * Author: Nicolas Pitre <npitre@baylibre.com>
0006  */
0007 
0008 #include <linux/bitfield.h>
0009 #include <linux/bitmap.h>
0010 #include <linux/device.h>
0011 #include <linux/errno.h>
0012 #include <linux/i3c/master.h>
0013 #include <linux/io.h>
0014 
0015 #include "hci.h"
0016 #include "dat.h"
0017 
0018 
0019 /*
0020  * Device Address Table Structure
0021  */
0022 
0023 #define DAT_1_AUTOCMD_HDR_CODE      W1_MASK(58, 51)
0024 #define DAT_1_AUTOCMD_MODE      W1_MASK(50, 48)
0025 #define DAT_1_AUTOCMD_VALUE     W1_MASK(47, 40)
0026 #define DAT_1_AUTOCMD_MASK      W1_MASK(39, 32)
0027 /*  DAT_0_I2C_DEVICE        W0_BIT_(31) */
0028 #define DAT_0_DEV_NACK_RETRY_CNT    W0_MASK(30, 29)
0029 #define DAT_0_RING_ID           W0_MASK(28, 26)
0030 #define DAT_0_DYNADDR_PARITY        W0_BIT_(23)
0031 #define DAT_0_DYNAMIC_ADDRESS       W0_MASK(22, 16)
0032 #define DAT_0_TS            W0_BIT_(15)
0033 #define DAT_0_MR_REJECT         W0_BIT_(14)
0034 /*  DAT_0_SIR_REJECT        W0_BIT_(13) */
0035 /*  DAT_0_IBI_PAYLOAD       W0_BIT_(12) */
0036 #define DAT_0_STATIC_ADDRESS        W0_MASK(6, 0)
0037 
0038 #define dat_w0_read(i)      readl(hci->DAT_regs + (i) * 8)
0039 #define dat_w1_read(i)      readl(hci->DAT_regs + (i) * 8 + 4)
0040 #define dat_w0_write(i, v)  writel(v, hci->DAT_regs + (i) * 8)
0041 #define dat_w1_write(i, v)  writel(v, hci->DAT_regs + (i) * 8 + 4)
0042 
0043 static inline bool dynaddr_parity(unsigned int addr)
0044 {
0045     addr |= 1 << 7;
0046     addr += addr >> 4;
0047     addr += addr >> 2;
0048     addr += addr >> 1;
0049     return (addr & 1);
0050 }
0051 
0052 static int hci_dat_v1_init(struct i3c_hci *hci)
0053 {
0054     unsigned int dat_idx;
0055 
0056     if (!hci->DAT_regs) {
0057         dev_err(&hci->master.dev,
0058             "only DAT in register space is supported at the moment\n");
0059         return -EOPNOTSUPP;
0060     }
0061     if (hci->DAT_entry_size != 8) {
0062         dev_err(&hci->master.dev,
0063             "only 8-bytes DAT entries are supported at the moment\n");
0064         return -EOPNOTSUPP;
0065     }
0066 
0067     /* use a bitmap for faster free slot search */
0068     hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
0069     if (!hci->DAT_data)
0070         return -ENOMEM;
0071 
0072     /* clear them */
0073     for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
0074         dat_w0_write(dat_idx, 0);
0075         dat_w1_write(dat_idx, 0);
0076     }
0077 
0078     return 0;
0079 }
0080 
0081 static void hci_dat_v1_cleanup(struct i3c_hci *hci)
0082 {
0083     bitmap_free(hci->DAT_data);
0084     hci->DAT_data = NULL;
0085 }
0086 
0087 static int hci_dat_v1_alloc_entry(struct i3c_hci *hci)
0088 {
0089     unsigned int dat_idx;
0090 
0091     dat_idx = find_first_zero_bit(hci->DAT_data, hci->DAT_entries);
0092     if (dat_idx >= hci->DAT_entries)
0093         return -ENOENT;
0094     __set_bit(dat_idx, hci->DAT_data);
0095 
0096     /* default flags */
0097     dat_w0_write(dat_idx, DAT_0_SIR_REJECT | DAT_0_MR_REJECT);
0098 
0099     return dat_idx;
0100 }
0101 
0102 static void hci_dat_v1_free_entry(struct i3c_hci *hci, unsigned int dat_idx)
0103 {
0104     dat_w0_write(dat_idx, 0);
0105     dat_w1_write(dat_idx, 0);
0106     __clear_bit(dat_idx, hci->DAT_data);
0107 }
0108 
0109 static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
0110                     unsigned int dat_idx, u8 address)
0111 {
0112     u32 dat_w0;
0113 
0114     dat_w0 = dat_w0_read(dat_idx);
0115     dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY);
0116     dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) |
0117           (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0);
0118     dat_w0_write(dat_idx, dat_w0);
0119 }
0120 
0121 static void hci_dat_v1_set_static_addr(struct i3c_hci *hci,
0122                        unsigned int dat_idx, u8 address)
0123 {
0124     u32 dat_w0;
0125 
0126     dat_w0 = dat_w0_read(dat_idx);
0127     dat_w0 &= ~DAT_0_STATIC_ADDRESS;
0128     dat_w0 |= FIELD_PREP(DAT_0_STATIC_ADDRESS, address);
0129     dat_w0_write(dat_idx, dat_w0);
0130 }
0131 
0132 static void hci_dat_v1_set_flags(struct i3c_hci *hci, unsigned int dat_idx,
0133                  u32 w0_flags, u32 w1_flags)
0134 {
0135     u32 dat_w0, dat_w1;
0136 
0137     dat_w0 = dat_w0_read(dat_idx);
0138     dat_w1 = dat_w1_read(dat_idx);
0139     dat_w0 |= w0_flags;
0140     dat_w1 |= w1_flags;
0141     dat_w0_write(dat_idx, dat_w0);
0142     dat_w1_write(dat_idx, dat_w1);
0143 }
0144 
0145 static void hci_dat_v1_clear_flags(struct i3c_hci *hci, unsigned int dat_idx,
0146                    u32 w0_flags, u32 w1_flags)
0147 {
0148     u32 dat_w0, dat_w1;
0149 
0150     dat_w0 = dat_w0_read(dat_idx);
0151     dat_w1 = dat_w1_read(dat_idx);
0152     dat_w0 &= ~w0_flags;
0153     dat_w1 &= ~w1_flags;
0154     dat_w0_write(dat_idx, dat_w0);
0155     dat_w1_write(dat_idx, dat_w1);
0156 }
0157 
0158 static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr)
0159 {
0160     unsigned int dat_idx;
0161     u32 dat_w0;
0162 
0163     for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) {
0164         dat_w0 = dat_w0_read(dat_idx);
0165         if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr)
0166             return dat_idx;
0167     }
0168 
0169     return -ENODEV;
0170 }
0171 
0172 const struct hci_dat_ops mipi_i3c_hci_dat_v1 = {
0173     .init           = hci_dat_v1_init,
0174     .cleanup        = hci_dat_v1_cleanup,
0175     .alloc_entry        = hci_dat_v1_alloc_entry,
0176     .free_entry     = hci_dat_v1_free_entry,
0177     .set_dynamic_addr   = hci_dat_v1_set_dynamic_addr,
0178     .set_static_addr    = hci_dat_v1_set_static_addr,
0179     .set_flags      = hci_dat_v1_set_flags,
0180     .clear_flags        = hci_dat_v1_clear_flags,
0181     .get_index      = hci_dat_v1_get_index,
0182 };