Richard Spiegel has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/30109
Change subject: Work in progress: Early eMMC phase 1 ......................................................................
Work in progress: Early eMMC phase 1
Global objective: Early ready of eMMC by sending CMD0 and CMD1.
This phase objective: Create bh720 driver to be used by phase 2.
BUG=b:118680303 TEST=
Change-Id: Ifd2a307ead37c62abca811654873c43c02ac2a4a Signed-off-by: Richard Spiegel richard.spiegel@silverbackltd.com --- A src/drivers/emmc/README A src/drivers/emmc/bh7720/Kconfig A src/drivers/emmc/bh7720/Makefile.inc A src/drivers/emmc/bh7720/bh720.c A src/include/device/emmc/bh720.h A src/include/device/emmc/emmc.h 6 files changed, 281 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/09/30109/1
diff --git a/src/drivers/emmc/README b/src/drivers/emmc/README new file mode 100644 index 0000000..b95b477 --- /dev/null +++ b/src/drivers/emmc/README @@ -0,0 +1,51 @@ +/* + * Documentation for eMMC host drivers + * + * This file is part of the coreboot project. + * + * Copyright 2018 Silverback Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +This folder has drivers for several eMMC hosts. There's a minimum set of +commands these drivers must implement, though it can implement more: +emmc_driver_init -> initializes all required registers of a particular host, + so that commands can be send. +emmc_send_command -> the host sends a command to the eMMC card, status is + returned. +emmc_get_ocr -> The OCR value is read. + +Commands description: +int emmc_driver_init(void *params); +Some parameters are always the same, so they don't need to be send for code +execution. Only parameters that are board dependent plus the base address +should be send. +The input is a void pointer to parameters, which is internally converted to +a pointer to structure, defined in the chip specific header file. Inside +this structure, the first 2 elements are common: (uint8_t) total and +(uint16_t/uint32_t) base_address. The remaining are chip specific,. +The return can be 0 if success, or a negative number if there's a problem. + +uint32_t emmc_send_command(uint8_t command, uint32_t argument); +Using the base address from emmc_driver_init, it sends commands to the eMMC +and return the host status at the moment the command was issued. This is only +for 48-bits commands (start, stop, direction,CRC77, command and argument). + +uint32_t emmc_get_ocr(uint32_t base_address); +This function can be called before or after PCI enumeration, as it receives +the base address to use. If the base address is IO, the upper word should +be 0. It assumes that CMD1 was already issued, and returns the OCR received +from the eMMC. + +Generally speaking, emmc_driver_init must be used at romstage, while the +other 2 can be romstage or ramstage, though if PCI access is needed by the +particular chip to execute them, then they must be either romstage or have +a device declared to be used in ramstage. diff --git a/src/drivers/emmc/bh7720/Kconfig b/src/drivers/emmc/bh7720/Kconfig new file mode 100644 index 0000000..27b5c80 --- /dev/null +++ b/src/drivers/emmc/bh7720/Kconfig @@ -0,0 +1,2 @@ +config DRIVERS_EMMC_BH720 + bool diff --git a/src/drivers/emmc/bh7720/Makefile.inc b/src/drivers/emmc/bh7720/Makefile.inc new file mode 100644 index 0000000..e282a67 --- /dev/null +++ b/src/drivers/emmc/bh7720/Makefile.inc @@ -0,0 +1,2 @@ +romstage-$(CONFIG_DRIVERS_EMMC_BH720) += bh720.c +ramstage-$(CONFIG_DRIVERS_EMMC_BH720) += bh720.c diff --git a/src/drivers/emmc/bh7720/bh720.c b/src/drivers/emmc/bh7720/bh720.c new file mode 100644 index 0000000..ebd48d8 --- /dev/null +++ b/src/drivers/emmc/bh7720/bh720.c @@ -0,0 +1,132 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Silverback Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <rules.h> +#include <device/pci_def.h> +#include <device/emmc/emmc.h> +#include <device/emmc/bh720.h> + +static uint8_t *base_ptr; +static boolean flag = false; + +static void pci_set8(uint32_t dev, uint8_t reg, uint8_t bits) +{ + uint8_t value; + value = pci_read_config8(dev, reg); + value |= bits; + pci_write_config8(dev, reg, value); +} + +static void pci_clear8(uint32_t dev, uint8_t reg, uint8_t bits) +{ + uint8_t value, mask; + mask = ~bits; + value = pci_read_config8(dev, reg); + value &= mask; + pci_write_config8(dev, reg, value); +} + +static void pci_set32(uint32_t dev, uint8_t reg, uint32_t bits) +{ + uint32_t value; + value = pci_read_config32(dev, reg); + value |= bits; + pci_write_config32(dev, reg, value); +} + +static void pci_clear32(uint32_t dev, uint8_t reg, uint32_t bits) +{ + uint32_t value, mask; + mask = ~bits; + value = pci_read_config32(dev, reg); + value &= mask; + pci_write_config32(dev, reg, value); +} + +static void program_base(uint32_t dev, uint32_t base) +{ +} + +static void program_id(uint32_t dev, uint32_t id) +{ +} + +static uint32_t read_base(uint32_t dev, uint32_t id) +{ + uint32_t bridge_dev; + /* + * Read bridge, check if programmed. If programmed, generate + * bridge_dev and read/return base address. + */ + + /* + * Program bridge and base address. If (id) program_id. + * Set flag to indicate need of desprogramming bridge and BAR0. + */ +} + +int emmc_driver_init(void *params) +{ + bh720_params *param = (bh720_params *)params; + uint32_t temp; + uint32_t device = param->pci_dev; + uint32_t subsys_id = param->subsys_vend_dev_id; + uint8_t total = param->total + uint8_t mode = DEFAUT_MODE; + + base_ptr = (uint8_t *)param->base_address; + if (total > 4) + mode = param->mode; + if ((total == 0) || (total == 2)) + return EMMC_STATUS_INVALID_PARAM; + if (total == 1) { + temp = read_base(device, subsys_id); + param = (bh720_params *)temp; + if(flag) { + } + return EMMC_STATUS_SUCCESS; + } + if ((total > 3) { + if (subsys_id && (mode & MODE_VEND_DEV)) + program_id(device, subsys_id); +#if defined(__SIMPLE_DEVICE__) + if (mode > MODE_VEND_DEV) + return EMMC_STATUS_INVALID_STAGE; +#endif + if (mode & MODE_DIS_SD) { + } + if (mode & MODE_VCCQ_18) { + } + if (mode & MODE_POWER_SAVE) { + } + if (mode & MODE_L1_TIMER) { + } + if (mode & MODE_IDDQ) { + } + if (mode & MODE_TUNNING) { + } + if (mode & MODE_DLL_CLK_PHASE) { + } + return EMMC_STATUS_SUCCESS; +} + +uint32_t emmc_send_command(uint8_t command, uint32_t argument) +{ +} + +uint32_t emmc_get_ocr(uint32_t base_address) +{ +} + diff --git a/src/include/device/emmc/bh720.h b/src/include/device/emmc/bh720.h new file mode 100644 index 0000000..ca8faf5 --- /dev/null +++ b/src/include/device/emmc/bh720.h @@ -0,0 +1,54 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Silverback Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __BH720_H__ +#define __BH720_H__ + +#include <types.h> + +struct bh720_params { + uint8_t total; /* Note 1 */ + uintptr_t base_address; /* memory address */ + uint32_t pci_dev; /* PCI_DEV(bus, slot, func) */ + uint32_t subsys_vend_dev_id; /* if 0 or total = 3, do not set */ + uint8_t mode; /* optional, note 2 */ +}; /* total 5 parameters, so if all parameters, total = 5 */ + +#define MODE_VEND_DEV BIT(0) +#define MODE_DIS_SD BIT(1) +#define MODE_VCCQ_18 BIT(2) +#define MODE_POWER_SAVE BIT(3) +#define MODE_L1_TIMER BIT(4) +#define MODE_IDDQ BIT(5) +#define MODE_TUNNING BIT(6) +#define MODE_DLL_CLK_PHASE BIT(7) + +/* + * Note 1: The value of total shold be between 3 and 5, so value of 1 meaning + * is: + * A) pci_dev is relative to the bridge the host resides. + * B) If the bridge has not been programmed, then program the BAR with base + * adress. + * C) If bridge is programmed, then read BAR0 into base_address. + * D) If subsys_vend_dev_id is provided and (B) than program subsystem vendor + * and device IDs. + * + * Note 2: MODE_DIS_SD, MODE_VCCQ_18, MODE_POWER_SAVE, MODE_IDDQ, MODE_TUNNING, + * MODE_DLL_CLK_PHASE can only be set in ramstage, with a BH720 device defined, + * because they access PCI config space above 0xff. + */ +#define DEFAUT_MODE MODE_VEND_DEV + +#endif diff --git a/src/include/device/emmc/emmc.h b/src/include/device/emmc/emmc.h new file mode 100644 index 0000000..a2305f6 --- /dev/null +++ b/src/include/device/emmc/emmc.h @@ -0,0 +1,40 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Silverback Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __EMMC_H__ +#define __EMMC_H__ + +#define EMMC_PARAM_BYTE 1 +#define EMMC_PARAM_WORD 2 +#define EMMC_PARAM_DWORD 3 +#define EMMC_PARAM_QWORD 4 +#define EMMC_PARAM_PCI_DEV 5 + +#define EMMC_STATUS_SUCCESS 0 +#define EMMC_STATUS_INVALID_PARAM -1 +#define EMMC_STATUS_NO_BASE_ADDRESS -2 /* drive not initialized */ +#define EMMC_STATUS_INVALID_BASE_ADDR -3 /* invalid base size */ +#define EMMC_STATUS_HOST_BUSY -4 /* bit 31 of OCR 0b */ +#define EMMC_STATUS_INVALID_STAGE -5 /* PCI reg > 0xff in romstage */ + +int emmc_driver_init(void *params); +uint32_t emmc_send_command(uint8_t command, uint32_t argument); +uint32_t emmc_get_ocr(uint32_t base_address); + +int emmc_go_idle(void); +int emmc_go_ready(uint32_t argument); /* CMD1 argument depends on board/host */ +int emmc_check_ready{uint32_t *ocr, uint32_t base_address); + +#endif