firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_drivers-mmc-host-sdhci-p...

276 lines
6.9 KiB
Diff

--- linux-4.9.37/drivers/mmc/host/sdhci-proc.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/mmc/host/sdhci-proc.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include "sdhci.h"
+#include "sdhci-proc.h"
+
+#define MCI_PARENT "mci"
+#define MCI_STATS_PROC "mci_info"
+#define MAX_CLOCK_SCALE 4
+
+unsigned int slot_index;
+struct mmc_host *mci_host[MCI_SLOT_NUM] = {NULL};
+static struct proc_dir_entry *proc_mci_dir;
+
+static char *card_type[MAX_CARD_TYPE + 1] = {
+ "MMC card",
+ "SD card",
+ "SDIO card",
+ "SD combo (IO+mem) card",
+ "unknown"
+};
+static char *clock_unit[MAX_CLOCK_SCALE] = {
+ "Hz",
+ "KHz",
+ "MHz",
+ "GHz"
+};
+
+static char *mci_get_card_type(unsigned int sd_type)
+{
+ if (sd_type >= MAX_CARD_TYPE)
+ return card_type[MAX_CARD_TYPE];
+ else
+ return card_type[sd_type];
+}
+
+static unsigned int analyze_clock_scale(unsigned int clock, unsigned int *clock_val)
+{
+ unsigned int scale = 0;
+ unsigned int tmp = clock;
+
+ while (1) {
+ tmp = tmp / 1000; /* 1000 for clk calculate */
+ if (tmp > 0) {
+ *clock_val = tmp;
+ scale++;
+ } else {
+ break;
+ }
+ }
+ return scale;
+}
+
+static inline int is_card_uhs(unsigned char timing)
+{
+ return timing >= MMC_TIMING_UHS_SDR12 &&
+ timing <= MMC_TIMING_UHS_DDR50;
+};
+
+static inline int is_card_hs(unsigned char timing)
+{
+ return timing == MMC_TIMING_SD_HS || timing == MMC_TIMING_MMC_HS;
+};
+
+static void mci_stats_seq_printout(struct seq_file *s)
+{
+ unsigned int index_mci;
+ unsigned int clock;
+ unsigned int clock_scale;
+ unsigned int clock_value = 0;
+ const char *type = NULL;
+ static struct mmc_host *mmc = NULL;
+ const char *uhs_bus_speed_mode = "";
+ static const char *uhs_speeds[] = {
+ [UHS_SDR12_BUS_SPEED] = "SDR12 ",
+ [UHS_SDR25_BUS_SPEED] = "SDR25 ",
+ [UHS_SDR50_BUS_SPEED] = "SDR50 ",
+ [UHS_SDR104_BUS_SPEED] = "SDR104 ",
+ [UHS_DDR50_BUS_SPEED] = "DDR50 ",
+ };
+ unsigned int speed_class, grade_speed_uhs;
+ struct card_info *info = NULL;
+ unsigned int present;
+ struct sdhci_host *host = NULL;
+
+ for (index_mci = 0; index_mci < MCI_SLOT_NUM; index_mci++) {
+ mmc = mci_host[index_mci];
+ if (mmc == NULL) {
+ seq_printf(s, "MCI%d: invalid\n", index_mci);
+ continue;
+ } else {
+ seq_printf(s, "MCI%d", index_mci);
+ }
+ host = mmc_priv(mmc);
+ info = &host->c_info;
+
+ present = host->mmc->ops->get_cd(host->mmc);
+ if (present)
+ seq_puts(s, ": pluged");
+ else
+ seq_puts(s, ": unplugged");
+
+ if (info->card_connect != CARD_CONNECT) {
+ if (mmc->card_status == MMC_CARD_INIT_FAIL)
+ seq_puts(s, "_init_failed\n");
+ else
+ seq_puts(s, "_disconnected\n");
+ } else {
+ seq_puts(s, "_connected\n");
+
+ seq_printf(s, "\tType: %s",
+ mci_get_card_type(info->card_type));
+
+ if (info->card_state & MMC_STATE_BLOCKADDR) {
+ if (info->card_state & MMC_CARD_SDXC)
+ type = "SDXC";
+ else
+ type = "SDHC";
+ seq_printf(s, "(%s)\n", type);
+ }
+
+ if (is_card_uhs(info->timing) &&
+ info->sd_bus_speed < ARRAY_SIZE(uhs_speeds))
+ uhs_bus_speed_mode =
+ uhs_speeds[info->sd_bus_speed];
+
+ seq_printf(s, "\tMode: %s%s%s%s\n",
+ is_card_uhs(info->timing) ? "UHS " :
+ (is_card_hs(info->timing) ? "HS " : ""),
+ info->timing == MMC_TIMING_MMC_HS400 ? "HS400 " :
+ (info->timing == MMC_TIMING_MMC_HS200 ? "HS200 " : ""),
+ info->timing == MMC_TIMING_MMC_DDR52 ? "DDR " : "",
+ uhs_bus_speed_mode);
+
+ speed_class = UNSTUFF_BITS(info->ssr, 56, 8); /* 56 equal 440 -384 */
+ grade_speed_uhs = UNSTUFF_BITS(info->ssr, 12, 4); /* 12 equal 396 - 384 */
+ seq_printf(s, "\tSpeed Class: Class %s\n",
+ (speed_class == 0x00) ? "0" :
+ (speed_class == 0x01) ? "2" :
+ (speed_class == 0x02) ? "4" :
+ (speed_class == 0x03) ? "6" :
+ (speed_class == 0x04) ? "10" :
+ "Reserved");
+ seq_printf(s, "\tUhs Speed Grade: %s\n",
+ (grade_speed_uhs == 0x00) ?
+ "Less than 10MB/sec(0h)" :
+ (grade_speed_uhs == 0x01) ?
+ "10MB/sec and above(1h)" :
+ "Reserved");
+
+ clock = info->card_support_clock;
+ clock_scale = analyze_clock_scale(clock, &clock_value);
+ seq_printf(s, "\tHost work clock: %d%s\n",
+ clock_value, clock_unit[clock_scale]);
+
+ clock = info->card_support_clock;
+ clock_scale = analyze_clock_scale(clock, &clock_value);
+ seq_printf(s, "\tCard support clock: %d%s\n",
+ clock_value, clock_unit[clock_scale]);
+
+ clock = mmc->actual_clock;
+ clock_scale = analyze_clock_scale(clock, &clock_value);
+ seq_printf(s, "\tCard work clock: %d%s\n",
+ clock_value, clock_unit[clock_scale]);
+
+ /* add card read/write error count */
+ seq_printf(s, "\tCard error count: %d\n",
+ host->error_count);
+ }
+ }
+}
+
+/* proc interface setup */
+static void *mci_seq_start(struct seq_file *s, loff_t *pos)
+{
+ /* counter is used to tracking multi proc interfaces
+ * We have only one interface so return zero
+ * pointer to start the sequence.
+ */
+ static unsigned long counter;
+
+ if (*pos == 0)
+ return &counter;
+
+ *pos = 0;
+ return NULL;
+}
+
+/* proc interface next */
+static void *mci_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ (*pos)++;
+ if (*pos >= MCI_SLOT_NUM)
+ return NULL;
+
+ return NULL;
+}
+
+/* define parameters where showed in proc file */
+static int mci_stats_seq_show(struct seq_file *s, void *v)
+{
+ mci_stats_seq_printout(s);
+ return 0;
+}
+
+/* proc interface stop */
+static void mci_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+/* proc interface operation */
+static const struct seq_operations mci_stats_seq_ops = {
+ .start = mci_seq_start,
+ .next = mci_seq_next,
+ .stop = mci_seq_stop,
+ .show = mci_stats_seq_show
+};
+
+/* proc file open */
+static int mci_stats_proc_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &mci_stats_seq_ops);
+};
+
+/* proc file operation */
+static const struct file_operations mci_stats_proc_ops = {
+ .owner = THIS_MODULE,
+ .open = mci_stats_proc_open,
+ .read = seq_read,
+ .release = seq_release
+};
+
+int mci_proc_init(void)
+{
+ struct proc_dir_entry *proc_stats_entry = NULL;
+
+ proc_mci_dir = proc_mkdir(MCI_PARENT, NULL);
+ if (!proc_mci_dir) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, MCI_PARENT);
+ return 1;
+ }
+
+ proc_stats_entry = proc_create(MCI_STATS_PROC,
+ 0, proc_mci_dir, &mci_stats_proc_ops);
+ if (!proc_stats_entry) {
+ pr_err("%s: failed to create proc file %s\n",
+ __func__, MCI_STATS_PROC);
+ return 1;
+ }
+
+ return 0;
+}
+
+int mci_proc_shutdown(void)
+{
+ if (proc_mci_dir) {
+ remove_proc_entry(MCI_STATS_PROC, proc_mci_dir);
+ remove_proc_entry(MCI_PARENT, NULL);
+ proc_mci_dir = NULL;
+ }
+
+ return 0;
+}