blob: 6623623c962b8324893b68d0b07721f54862daee [file] [log] [blame]
/*
* Copyright (c) 2019 Samsung Electronics Co., Ltd.
*
* Author: Shradha Todi <shradha.t@samsung.com>
*
* AB chip information
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/airbrush-sm-ctrl.h>
#include <linux/mfd/abc-pcie.h>
#define LOTID_LBIT 0
#define LOTID_MASK 0x1FFFFF
#define LOTID_NO_OF_BITS 21
#define WAFER_LBIT 21
#define WAFER_MASK 0x1F
#define WAFER_NO_OF_BITS 5
#define XCOORD_LBIT 26
#define XCOORD_MASK 0xFF
#define XCOORD_NO_OF_BITS 8
#define YCOORD_LBIT 2
#define YCOORD_MASK 0xFF
#define YCOORD_NO_OF_BITS 8
#define PRO_LINE_LBIT 2
#define PRO_LINE_MASK 0x3
#define SUB_REV_LBIT 16
#define SUB_REV_MASK 0xF
#define MAIN_REV_LBIT 20
#define MAIN_REV_MASK 0xF
#define PKG_REV_LBIT 24
#define PKG_REV_MASK 0xFF
static char table[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
static u32 reverse_bits(u32 n, u32 no_of_bits)
{
u32 rev = 0;
int i;
for (i = 0; i < no_of_bits; i++) {
rev <<= 1;
if (n & 1)
rev ^= 1;
n >>= 1;
}
return rev;
}
static void to_base_36(u32 lotid, char *ans)
{
u32 n = lotid;
u32 i = 4;
while (n > 0 && i >= 0) {
ans[i--] = table[n % 36];
n = n / 36;
}
ans[5] = '\0';
}
static int chip_info_show(struct seq_file *m, void *v)
{
u32 chip0, chip1, chip2, chip3;
u32 lotid, pro_line;
char lot[6];
int ret;
ret = ABC_READ(0x10BB0004, &chip0);
if (ret) {
seq_puts(m, "AB Unavailable (powered down?)\n");
return 0;
}
ABC_READ(0x10BB0008, &chip1);
ABC_READ(0x10BB000C, &chip2);
ABC_READ(0x10BB0010, &chip3);
lotid = reverse_bits(((chip0 >> LOTID_LBIT) & LOTID_MASK),
LOTID_NO_OF_BITS);
pro_line = ((chip1 >> PRO_LINE_LBIT) & PRO_LINE_MASK);
if (pro_line == 0x1)
lot[0] = 'N';
else if (pro_line == 0x2)
lot[0] = 'S';
to_base_36(lotid, lot);
seq_puts(m, "==================================================\n");
seq_printf(m, "ECID[127:96][95:64][63:32][31:00] = %08X_%08X_%08X_%08X\n",
chip3, chip2, chip1, chip0);
seq_puts(m, "--------------------------------------------------\n");
seq_printf(m, " Wafer Number: %d\n", reverse_bits(((chip0 >>
WAFER_LBIT) & WAFER_MASK), WAFER_NO_OF_BITS));
seq_printf(m, " X Position: %d\n", reverse_bits((((chip0 >>
XCOORD_LBIT) | (chip1 << 6)) &
XCOORD_MASK), XCOORD_NO_OF_BITS));
seq_printf(m, " Y Position: %d\n", reverse_bits(((chip1 >>
YCOORD_LBIT) & YCOORD_MASK), YCOORD_NO_OF_BITS));
seq_printf(m, " Main Revision: %d\n", ((chip3 >> MAIN_REV_LBIT) &
MAIN_REV_MASK));
seq_printf(m, " Sub Revision: %d\n", ((chip3 >> SUB_REV_LBIT) &
SUB_REV_MASK));
seq_printf(m, " PKG Revision: %d\n", ((chip3 >> PKG_REV_LBIT) &
PKG_REV_MASK));
seq_printf(m, " Lot ID: %s\n", lot);
seq_printf(m, " IPU RO: %d\n", get_ipu_ro());
seq_printf(m, " TPU RO: %d\n", get_tpu_ro());
seq_puts(m, "==================================================\n");
return 0;
}
int chip_info_open(struct inode *inode, struct file *file)
{
return single_open(file, chip_info_show, NULL);
}